(function () {
  UEDITOR_CONFIG = window.UEDITOR_CONFIG || {};
  var baidu = window.baidu || {};
  window.baidu = baidu;
  window.UE = baidu.editor = {plugins: {}, commands: {}, instants: {}, I18N: {}, _customizeUI: {}, version: "4.0.0", constants: {STATEFUL: {DISABLED: -1, OFF: 0, ON: 1}}};
  var dom = UE.dom = {};
  var browser = UE.browser = function () {
    var agent = navigator.userAgent.toLowerCase(), opera = window.opera,
      browser = {ie: /(msie\s|trident.*rv:)([\w.]+)/i.test(agent), opera: !!opera && opera.version, webkit: agent.indexOf(" applewebkit/") > -1, mac: agent.indexOf("macintosh") > -1, quirks: document.compatMode == "BackCompat"};
    browser.gecko = navigator.product == "Gecko" && !browser.webkit && !browser.opera && !browser.ie;
    var version = 0;
    if (browser.ie) {
      var v1 = agent.match(/(?:msie\s([\w.]+))/);
      var v2 = agent.match(/(?:trident.*rv:([\w.]+))/);
      if (v1 && v2 && v1[1] && v2[1]) {
        version = Math.max(v1[1] * 1, v2[1] * 1)
      } else if (v1 && v1[1]) {
        version = v1[1] * 1
      } else if (v2 && v2[1]) {
        version = v2[1] * 1
      } else {
        version = 0
      }
      browser.ie11Compat = document.documentMode == 11;
      browser.ie9Compat = document.documentMode == 9;
      browser.ie8 = !!document.documentMode;
      browser.ie8Compat = document.documentMode == 8;
      browser.ie7Compat = version == 7 && !document.documentMode || document.documentMode == 7;
      browser.ie6Compat = version < 7 || browser.quirks;
      browser.ie9above = version > 8;
      browser.ie9below = version < 9;
      browser.ie11above = version > 10;
      browser.ie11below = version < 11
    }
    if (browser.gecko) {
      var geckoRelease = agent.match(/rv:([\d\.]+)/);
      if (geckoRelease) {
        geckoRelease = geckoRelease[1].split(".");
        version = geckoRelease[0] * 1e4 + (geckoRelease[1] || 0) * 100 + (geckoRelease[2] || 0) * 1
      }
    }
    if (/chrome\/(\d+\.\d)/i.test(agent)) {
      browser.chrome = +RegExp["$1"]
    }
    if (/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)) {
      browser.safari = +(RegExp["$1"] || RegExp["$2"])
    }
    if (browser.opera) version = parseFloat(opera.version());
    if (browser.webkit) version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]);
    browser.version = version;
    browser.isCompatible = !browser.mobile && (browser.ie && version >= 6 || browser.gecko && version >= 10801 || browser.opera && version >= 9.5 || browser.air && version >= 1 || browser.webkit && version >= 522 || false);
    return browser
  }();
  var ie = browser.ie, webkit = browser.webkit, gecko = browser.gecko, opera = browser.opera;
  var utils = UE.utils = {
    each: function (obj, iterator, context) {
      if (obj == null) return;
      if (obj.length === +obj.length) {
        for (var i = 0, l = obj.length; i < l; i++) {
          if (iterator.call(context, obj[i], i, obj) === false) return false
        }
      } else {
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            if (iterator.call(context, obj[key], key, obj) === false) return false
          }
        }
      }
    }, makeInstance: function (obj) {
      var noop = new Function;
      noop.prototype = obj;
      obj = new noop;
      noop.prototype = null;
      return obj
    }, isObject: function (item) {
      return item && typeof item === "object" && !Array.isArray(item)
    }, merge: function (target, source) {
      var output = Object.assign({}, target);
      if (this.isObject(target) && this.isObject(source)) {
        Object.keys(source).forEach(key => {
          if (this.isObject(source[key])) {
            if (!(key in target)) {
              Object.assign(output, {[key]: source[key]})
            } else {
              output[key] = this.merge(target[key], source[key])
            }
          } else {
            Object.assign(output, {[key]: source[key]})
          }
        })
      }
      return output
    }, extend: function (t, s, b) {
      if (s) {
        for (var k in s) {
          if (!b || !t.hasOwnProperty(k)) {
            t[k] = s[k]
          }
        }
      }
      return t
    }, extend2: function (t) {
      var a = arguments;
      for (var i = 1; i < a.length; i++) {
        var x = a[i];
        for (var k in x) {
          if (!t.hasOwnProperty(k)) {
            t[k] = x[k]
          }
        }
      }
      return t
    }, inherits: function (subClass, superClass) {
      var oldP = subClass.prototype, newP = utils.makeInstance(superClass.prototype);
      utils.extend(newP, oldP, true);
      subClass.prototype = newP;
      return newP.constructor = subClass
    }, bind: function (fn, context) {
      return function () {
        return fn.apply(context, arguments)
      }
    }, defer: function (fn, delay, exclusion) {
      var timerID;
      return function () {
        if (exclusion) {
          clearTimeout(timerID)
        }
        timerID = setTimeout(fn, delay)
      }
    }, indexOf: function (array, item, start) {
      var index = -1;
      start = this.isNumber(start) ? start : 0;
      this.each(array, function (v, i) {
        if (i >= start && v === item) {
          index = i;
          return false
        }
      });
      return index
    }, removeItem: function (array, item) {
      for (var i = 0, l = array.length; i < l; i++) {
        if (array[i] === item) {
          array.splice(i, 1);
          i--
        }
      }
    }, trim: function (str) {
      return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, "")
    }, listToMap: function (list) {
      if (!list) return {};
      list = utils.isArray(list) ? list : list.split(",");
      for (var i = 0, ci, obj = {}; ci = list[i++];) {
        obj[ci.toUpperCase()] = obj[ci] = 1
      }
      return obj
    }, unhtml: function (str, reg) {
      return str ? str.replace(reg || /[&<">'](?:(amp|lt|ldquo|rdquo|quot|gt|#39|nbsp|#\d+);)?/g, function (a, b) {
        if (b) {
          return a
        } else {
          return {"<": "&lt;", "&": "&amp;", '"': "&quot;", "“": "&ldquo;", "”": "&rdquo;", ">": "&gt;", "'": "&#39;"}[a]
        }
      }) : ""
    }, html: function (str) {
      return str ? str.replace(/&((g|l|quo|ldquo|rdquo)t|amp|#39|nbsp);/g, function (m) {
        return {"&lt;": "<", "&amp;": "&", "&quot;": '"', "&ldquo;": "“", "&rdquo;": "”", "&gt;": ">", "&#39;": "'", "&nbsp;": " "}[m]
      }) : ""
    }, cssStyleToDomStyle: function () {
      var test = document.createElement("div").style, cache = {float: test.cssFloat !== undefined ? "cssFloat" : test.styleFloat !== undefined ? "styleFloat" : "float"};
      return function (cssName) {
        return cache[cssName] || (cache[cssName] = cssName.toLowerCase().replace(/-./g, function (match) {
          return match.charAt(1).toUpperCase()
        }))
      }
    }(), loadFile: function () {
      var tmpList = [];

      function getItem(doc, obj) {
        try {
          for (var i = 0, ci; ci = tmpList[i++];) {
            if (ci.doc === doc && ci.url == (obj.src || obj.href)) {
              return ci
            }
          }
        } catch (e) {
          return null
        }
      }

      return function (doc, obj, fn) {
        var item = getItem(doc, obj);
        if (item) {
          if (item.ready) {
            fn && fn()
          } else {
            item.funs.push(fn)
          }
          return
        }
        tmpList.push({doc: doc, url: obj.src || obj.href, funs: [fn]});
        if (!doc.body) {
          var html = [];
          for (var p in obj) {
            if (p == "tag") continue;
            html.push(p + '="' + obj[p] + '"')
          }
          doc.write("<" + obj.tag + " " + html.join(" ") + " ></" + obj.tag + ">");
          return
        }
        if (obj.id && doc.getElementById(obj.id)) {
          return
        }
        var element = doc.createElement(obj.tag);
        delete obj.tag;
        for (var p in obj) {
          element.setAttribute(p, obj[p])
        }
        element.onload = element.onreadystatechange = function () {
          if (!this.readyState || /loaded|complete/.test(this.readyState)) {
            item = getItem(doc, obj);
            if (item.funs.length > 0) {
              item.ready = 1;
              for (var fi; fi = item.funs.pop();) {
                fi()
              }
            }
            element.onload = element.onreadystatechange = null
          }
        };
        element.onerror = function () {
          throw Error("The load " + (obj.href || obj.src) + " fails,check the url settings of file ueditor.config.js ")
        };
        doc.getElementsByTagName("head")[0].appendChild(element)
      }
    }(), isEmptyObject: function (obj) {
      if (obj == null) return true;
      if (this.isArray(obj) || this.isString(obj)) return obj.length === 0;
      for (var key in obj) if (obj.hasOwnProperty(key)) return false;
      return true
    }, fixColor: function (name, value) {
      if (/color/i.test(name) && /rgba?/.test(value)) {
        var array = value.split(",");
        if (array.length > 3) return "";
        value = "#";
        for (var i = 0, color; color = array[i++];) {
          color = parseInt(color.replace(/[^\d]/gi, ""), 10).toString(16);
          value += color.length == 1 ? "0" + color : color
        }
        value = value.toUpperCase()
      }
      return value
    }, optCss: function (val) {
      var padding, margin, border;
      val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, function (str, key, name, val) {
        if (val.split(" ").length == 1) {
          switch (key) {
            case"padding":
              !padding && (padding = {});
              padding[name] = val;
              return "";
            case"margin":
              !margin && (margin = {});
              margin[name] = val;
              return "";
            case"border":
              return val == "initial" ? "" : str
          }
        }
        return str
      });

      function opt(obj, name) {
        if (!obj) {
          return ""
        }
        var t = obj.top, b = obj.bottom, l = obj.left, r = obj.right, val = "";
        if (!t || !l || !b || !r) {
          for (var p in obj) {
            val += ";" + name + "-" + p + ":" + obj[p] + ";"
          }
        } else {
          val += ";" + name + ":" + (t == b && b == l && l == r ? t : t == b && l == r ? t + " " + l : l == r ? t + " " + l + " " + b : t + " " + r + " " + b + " " + l) + ";"
        }
        return val
      }

      val += opt(padding, "padding") + opt(margin, "margin");
      return val.replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, "").replace(/;([ \n\r\t]+)|\1;/g, ";").replace(/(&((l|g)t|quot|#39))?;{2,}/g, function (a, b) {
        return b ? b + ";;" : ";"
      })
    }, clone: function (source, target) {
      var tmp;
      target = target || {};
      for (var i in source) {
        if (source.hasOwnProperty(i)) {
          tmp = source[i];
          if (typeof tmp == "object") {
            target[i] = utils.isArray(tmp) ? [] : {};
            utils.clone(source[i], target[i])
          } else {
            target[i] = tmp
          }
        }
      }
      return target
    }, transUnitToPx: function (val) {
      if (!/(pt|cm)/.test(val)) {
        return val
      }
      var unit;
      val.replace(/([\d.]+)(\w+)/, function (str, v, u) {
        val = v;
        unit = u
      });
      switch (unit) {
        case"cm":
          val = parseFloat(val) * 25;
          break;
        case"pt":
          val = Math.round(parseFloat(val) * 96 / 72)
      }
      return val + (val ? "px" : "")
    }, domReady: function () {
      var fnArr = [];

      function doReady(doc) {
        doc.isReady = true;
        for (var ci; ci = fnArr.pop(); ci()) {
        }
      }

      return function (onready, win) {
        win = win || window;
        var doc = win.document;
        onready && fnArr.push(onready);
        if (doc.readyState === "complete") {
          doReady(doc)
        } else {
          doc.isReady && doReady(doc);
          if (browser.ie && browser.version != 11) {
            (function () {
              if (doc.isReady) return;
              try {
                doc.documentElement.doScroll("left")
              } catch (error) {
                setTimeout(arguments.callee, 0);
                return
              }
              doReady(doc)
            })();
            win.attachEvent("onload", function () {
              doReady(doc)
            })
          } else {
            doc.addEventListener("DOMContentLoaded", function () {
              doc.removeEventListener("DOMContentLoaded", arguments.callee, false);
              doReady(doc)
            }, false);
            win.addEventListener("load", function () {
              doReady(doc)
            }, false)
          }
        }
      }
    }(), cssRule: browser.ie && browser.version != 11 ? function (key, style, doc) {
      var indexList, index;
      if (style === undefined || style && style.nodeType && style.nodeType == 9) {
        doc = style && style.nodeType && style.nodeType == 9 ? style : doc || document;
        indexList = doc.indexList || (doc.indexList = {});
        index = indexList[key];
        if (index !== undefined) {
          return doc.styleSheets[index].cssText
        }
        return undefined
      }
      doc = doc || document;
      indexList = doc.indexList || (doc.indexList = {});
      index = indexList[key];
      if (style === "") {
        if (index !== undefined) {
          doc.styleSheets[index].cssText = "";
          delete indexList[key];
          return true
        }
        return false
      }
      if (index !== undefined) {
        sheetStyle = doc.styleSheets[index]
      } else {
        sheetStyle = doc.createStyleSheet("", index = doc.styleSheets.length);
        indexList[key] = index
      }
      sheetStyle.cssText = style
    } : function (key, style, doc) {
      var head, node;
      if (style === undefined || style && style.nodeType && style.nodeType == 9) {
        doc = style && style.nodeType && style.nodeType == 9 ? style : doc || document;
        node = doc.getElementById(key);
        return node ? node.innerHTML : undefined
      }
      doc = doc || document;
      node = doc.getElementById(key);
      if (style === "") {
        if (node) {
          node.parentNode.removeChild(node);
          return true
        }
        return false
      }
      if (node) {
        node.innerHTML = style
      } else {
        node = doc.createElement("style");
        node.id = key;
        node.innerHTML = style;
        doc.getElementsByTagName("head")[0].appendChild(node)
      }
    }, sort: function (array, compareFn) {
      compareFn = compareFn || function (item1, item2) {
        return item1.localeCompare(item2)
      };
      for (var i = 0, len = array.length; i < len; i++) {
        for (var j = i, length = array.length; j < length; j++) {
          if (compareFn(array[i], array[j]) > 0) {
            var t = array[i];
            array[i] = array[j];
            array[j] = t
          }
        }
      }
      return array
    }, serializeParam: function (json) {
      var strArr = [];
      for (var i in json) {
        if (i == "method" || i == "timeout" || i == "async") continue;
        if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) {
          strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i]))
        } else if (utils.isArray(json[i])) {
          for (var j = 0; j < json[i].length; j++) {
            strArr.push(encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]))
          }
        }
      }
      return strArr.join("&")
    }, formatUrl: function (url) {
      var u = url.replace(/&&/g, "&");
      u = u.replace(/\?&/g, "?");
      u = u.replace(/&$/g, "");
      u = u.replace(/&#/g, "#");
      u = u.replace(/&+/g, "&");
      return u
    }, addStyleContent: function (cssContent) {
      var style = document.createElement("style");
      style.innerHTML = cssContent;
      document.head.appendChild(style)
    }, isCrossDomainUrl: function (url) {
      var a = document.createElement("a");
      a.href = url;
      if (browser.ie) {
        a.href = a.href
      }
      return !(a.protocol == location.protocol && a.hostname == location.hostname && (a.port == location.port || a.port == "80" && location.port == "" || a.port == "" && location.port == "80"))
    }, clearEmptyAttrs: function (obj) {
      for (var p in obj) {
        if (obj[p] === "") {
          delete obj[p]
        }
      }
      return obj
    }, str2json: function (s) {
      if (!utils.isString(s)) return null;
      if (window.JSON) {
        return JSON.parse(s)
      } else {
        return new Function("return " + utils.trim(s || ""))()
      }
    }, json2str: function () {
      if (window.JSON) {
        return JSON.stringify
      } else {
        var escapeMap = {"\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f", "\r": "\\r", '"': '\\"', "\\": "\\\\"};

        function encodeString(source) {
          if (/["\\\x00-\x1f]/.test(source)) {
            source = source.replace(/["\\\x00-\x1f]/g, function (match) {
              var c = escapeMap[match];
              if (c) {
                return c
              }
              c = match.charCodeAt();
              return "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16)
            })
          }
          return '"' + source + '"'
        }

        function encodeArray(source) {
          var result = ["["], l = source.length, preComma, i, item;
          for (i = 0; i < l; i++) {
            item = source[i];
            switch (typeof item) {
              case"undefined":
              case"function":
              case"unknown":
                break;
              default:
                if (preComma) {
                  result.push(",")
                }
                result.push(utils.json2str(item));
                preComma = 1
            }
          }
          result.push("]");
          return result.join("")
        }

        function pad(source) {
          return source < 10 ? "0" + source : source
        }

        function encodeDate(source) {
          return '"' + source.getFullYear() + "-" + pad(source.getMonth() + 1) + "-" + pad(source.getDate()) + "T" + pad(source.getHours()) + ":" + pad(source.getMinutes()) + ":" + pad(source.getSeconds()) + '"'
        }

        return function (value) {
          switch (typeof value) {
            case"undefined":
              return "undefined";
            case"number":
              return isFinite(value) ? String(value) : "null";
            case"string":
              return encodeString(value);
            case"boolean":
              return String(value);
            default:
              if (value === null) {
                return "null"
              } else if (utils.isArray(value)) {
                return encodeArray(value)
              } else if (utils.isDate(value)) {
                return encodeDate(value)
              } else {
                var result = ["{"], encode = utils.json2str, preComma, item;
                for (var key in value) {
                  if (Object.prototype.hasOwnProperty.call(value, key)) {
                    item = value[key];
                    switch (typeof item) {
                      case"undefined":
                      case"unknown":
                      case"function":
                        break;
                      default:
                        if (preComma) {
                          result.push(",")
                        }
                        preComma = 1;
                        result.push(encode(key) + ":" + encode(item))
                    }
                  }
                }
                result.push("}");
                return result.join("")
              }
          }
        }
      }
    }()
  };
  utils.each(["String", "Function", "Array", "Number", "RegExp", "Object", "Date"], function (v) {
    UE.utils["is" + v] = function (obj) {
      return Object.prototype.toString.apply(obj) == "[object " + v + "]"
    }
  });
  var EventBase = UE.EventBase = function () {
  };
  EventBase.prototype = {
    addListener: function (types, listener) {
      types = utils.trim(types).split(/\s+/);
      for (var i = 0, ti; ti = types[i++];) {
        getListener(this, ti, true).push(listener)
      }
    }, on: function (types, listener) {
      return this.addListener(types, listener)
    }, off: function (types, listener) {
      return this.removeListener(types, listener)
    }, trigger: function () {
      return this.fireEvent.apply(this, arguments)
    }, removeListener: function (types, listener) {
      types = utils.trim(types).split(/\s+/);
      for (var i = 0, ti; ti = types[i++];) {
        utils.removeItem(getListener(this, ti) || [], listener)
      }
    }, fireEvent: function () {
      var types = arguments[0];
      types = utils.trim(types).split(" ");
      for (var i = 0, ti; ti = types[i++];) {
        var listeners = getListener(this, ti), r, t, k;
        if (listeners) {
          k = listeners.length;
          while (k--) {
            if (!listeners[k]) continue;
            t = listeners[k].apply(this, arguments);
            if (t === true) {
              return t
            }
            if (t !== undefined) {
              r = t
            }
          }
        }
        if (t = this["on" + ti.toLowerCase()]) {
          r = t.apply(this, arguments)
        }
      }
      return r
    }
  };

  function getListener(obj, type, force) {
    var allListeners;
    type = type.toLowerCase();
    return (allListeners = obj.__allListeners || force && (obj.__allListeners = {})) && (allListeners[type] || force && (allListeners[type] = []))
  }

  var dtd = dom.dtd = function () {
    function _(s) {
      for (var k in s) {
        s[k.toUpperCase()] = s[k]
      }
      return s
    }

    var X = utils.extend2;
    var A = _({isindex: 1, fieldset: 1}), B = _({input: 1, button: 1, select: 1, textarea: 1, label: 1}), C = X(_({a: 1}), B), D = X({iframe: 1}, C),
      E = _({hr: 1, ul: 1, menu: 1, div: 1, blockquote: 1, noscript: 1, table: 1, center: 1, address: 1, dir: 1, pre: 1, h5: 1, dl: 1, h4: 1, noframes: 1, h6: 1, ol: 1, h1: 1, h3: 1, h2: 1}), F = _({ins: 1, del: 1, script: 1, style: 1}),
      G = X(_({mark: 1, b: 1, acronym: 1, bdo: 1, var: 1, "#": 1, abbr: 1, code: 1, br: 1, i: 1, cite: 1, kbd: 1, u: 1, strike: 1, s: 1, tt: 1, strong: 1, q: 1, samp: 1, em: 1, dfn: 1, span: 1}), F),
      H = X(_({sub: 1, img: 1, embed: 1, object: 1, sup: 1, basefont: 1, map: 1, applet: 1, font: 1, big: 1, small: 1}), G), I = X(_({p: 1}), H), J = X(_({iframe: 1}), H, B), K = _({
        img: 1,
        embed: 1,
        noscript: 1,
        br: 1,
        kbd: 1,
        center: 1,
        button: 1,
        basefont: 1,
        h5: 1,
        h4: 1,
        samp: 1,
        h6: 1,
        ol: 1,
        h1: 1,
        h3: 1,
        h2: 1,
        form: 1,
        font: 1,
        "#": 1,
        select: 1,
        menu: 1,
        ins: 1,
        abbr: 1,
        label: 1,
        code: 1,
        table: 1,
        script: 1,
        cite: 1,
        input: 1,
        iframe: 1,
        strong: 1,
        textarea: 1,
        noframes: 1,
        big: 1,
        small: 1,
        span: 1,
        hr: 1,
        sub: 1,
        bdo: 1,
        var: 1,
        div: 1,
        object: 1,
        sup: 1,
        strike: 1,
        dir: 1,
        map: 1,
        dl: 1,
        applet: 1,
        del: 1,
        isindex: 1,
        fieldset: 1,
        ul: 1,
        b: 1,
        acronym: 1,
        a: 1,
        blockquote: 1,
        i: 1,
        u: 1,
        s: 1,
        tt: 1,
        address: 1,
        q: 1,
        pre: 1,
        p: 1,
        em: 1,
        dfn: 1
      }), L = X(_({a: 0}), J), M = _({tr: 1}), N = _({"#": 1}), O = X(_({param: 1}), K), P = X(_({form: 1}), A, D, E, I), Q = _({li: 1, ol: 1, ul: 1}), R = _({style: 1, script: 1}), S = _({base: 1, link: 1, meta: 1, title: 1}), T = X(S, R),
      U = _({head: 1, body: 1}), V = _({html: 1});
    var block = _({address: 1, blockquote: 1, center: 1, dir: 1, div: 1, dl: 1, fieldset: 1, form: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, hr: 1, isindex: 1, menu: 1, noframes: 1, ol: 1, p: 1, pre: 1, table: 1, ul: 1}),
      empty = _({area: 1, base: 1, basefont: 1, br: 1, col: 1, command: 1, dialog: 1, embed: 1, hr: 1, img: 1, input: 1, isindex: 1, keygen: 1, link: 1, meta: 1, param: 1, source: 1, track: 1, wbr: 1});
    return _({
      $nonBodyContent: X(V, U, S),
      $block: block,
      $inline: L,
      $inlineWithA: X(_({a: 1}), L),
      $body: X(_({script: 1, style: 1}), block),
      $cdata: _({script: 1, style: 1}),
      $empty: empty,
      $nonChild: _({iframe: 1, textarea: 1}),
      $listItem: _({dd: 1, dt: 1, li: 1}),
      $list: _({ul: 1, ol: 1, dl: 1}),
      $isNotEmpty: _({table: 1, ul: 1, ol: 1, dl: 1, iframe: 1, area: 1, base: 1, col: 1, hr: 1, img: 1, embed: 1, input: 1, textarea: 1, link: 1, meta: 1, param: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1}),
      $removeEmpty: _({
        a: 1,
        abbr: 1,
        acronym: 1,
        address: 1,
        b: 1,
        bdo: 1,
        big: 1,
        cite: 1,
        code: 1,
        del: 1,
        dfn: 1,
        em: 1,
        font: 1,
        i: 1,
        ins: 1,
        label: 1,
        kbd: 1,
        q: 1,
        s: 1,
        samp: 1,
        small: 1,
        span: 1,
        strike: 1,
        strong: 1,
        sub: 1,
        sup: 1,
        tt: 1,
        u: 1,
        var: 1
      }),
      $removeEmptyBlock: _({p: 1, div: 1}),
      $tableContent: _({caption: 1, col: 1, colgroup: 1, tbody: 1, td: 1, tfoot: 1, th: 1, thead: 1, tr: 1, table: 1}),
      $notTransContent: _({pre: 1, script: 1, style: 1, textarea: 1}),
      html: U,
      head: T,
      style: N,
      script: N,
      body: P,
      base: {},
      link: {},
      meta: {},
      title: N,
      col: {},
      tr: _({td: 1, th: 1}),
      img: {},
      embed: {},
      colgroup: _({thead: 1, col: 1, tbody: 1, tr: 1, tfoot: 1}),
      noscript: P,
      td: P,
      br: {},
      th: P,
      center: P,
      kbd: L,
      button: X(I, E),
      basefont: {},
      h5: L,
      h4: L,
      samp: L,
      h6: L,
      ol: Q,
      h1: L,
      h3: L,
      option: N,
      h2: L,
      form: X(A, D, E, I),
      select: _({optgroup: 1, option: 1}),
      font: L,
      ins: L,
      menu: Q,
      abbr: L,
      label: L,
      table: _({thead: 1, col: 1, tbody: 1, tr: 1, colgroup: 1, caption: 1, tfoot: 1}),
      code: L,
      tfoot: M,
      cite: L,
      li: P,
      input: {},
      iframe: P,
      strong: L,
      textarea: N,
      noframes: P,
      big: L,
      small: L,
      span: _({"#": 1, br: 1, b: 1, strong: 1, u: 1, i: 1, em: 1, sub: 1, sup: 1, strike: 1, span: 1}),
      hr: L,
      dt: L,
      sub: L,
      optgroup: _({option: 1}),
      param: {},
      bdo: L,
      var: L,
      div: P,
      object: O,
      sup: L,
      dd: P,
      strike: L,
      area: {},
      dir: Q,
      map: X(_({area: 1, form: 1, p: 1}), A, F, E),
      applet: O,
      dl: _({dt: 1, dd: 1}),
      del: L,
      isindex: {},
      fieldset: X(_({legend: 1}), K),
      thead: M,
      ul: Q,
      acronym: L,
      b: L,
      a: X(_({a: 1}), J),
      blockquote: X(_({td: 1, tr: 1, tbody: 1, li: 1}), P),
      caption: L,
      i: L,
      u: L,
      tbody: M,
      s: L,
      address: X(D, I),
      tt: L,
      legend: L,
      q: L,
      pre: X(G, C),
      p: X(_({a: 1}), L),
      em: L,
      dfn: L,
      mark: L
    })
  }();

  function getDomNode(node, start, ltr, startFromChild, fn, guard) {
    var tmpNode = startFromChild && node[start], parent;
    !tmpNode && (tmpNode = node[ltr]);
    while (!tmpNode && (parent = (parent || node).parentNode)) {
      if (parent.tagName == "BODY" || guard && !guard(parent)) {
        return null
      }
      tmpNode = parent[ltr]
    }
    if (tmpNode && fn && !fn(tmpNode)) {
      return getDomNode(tmpNode, start, ltr, false, fn)
    }
    return tmpNode
  }

  var attrFix = ie && browser.version < 9 ? {
      tabindex: "tabIndex",
      readonly: "readOnly",
      for: "htmlFor",
      class: "className",
      maxlength: "maxLength",
      cellspacing: "cellSpacing",
      cellpadding: "cellPadding",
      rowspan: "rowSpan",
      colspan: "colSpan",
      usemap: "useMap",
      frameborder: "frameBorder"
    } : {tabindex: "tabIndex", readonly: "readOnly"},
    styleBlock = utils.listToMap(["-webkit-box", "-moz-box", "block", "list-item", "table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption"]);
  var domUtils = dom.domUtils = {
    NODE_ELEMENT: 1,
    NODE_DOCUMENT: 9,
    NODE_TEXT: 3,
    NODE_COMMENT: 8,
    NODE_DOCUMENT_FRAGMENT: 11,
    POSITION_IDENTICAL: 0,
    POSITION_DISCONNECTED: 1,
    POSITION_FOLLOWING: 2,
    POSITION_PRECEDING: 4,
    POSITION_IS_CONTAINED: 8,
    POSITION_CONTAINS: 16,
    fillChar: ie && browser.version === "6" ? "\ufeff" : "​",
    keys: {8: 1, 46: 1, 16: 1, 17: 1, 18: 1, 37: 1, 38: 1, 39: 1, 40: 1, 13: 1},
    getPosition: function (nodeA, nodeB) {
      if (nodeA === nodeB) {
        return 0
      }
      var node, parentsA = [nodeA], parentsB = [nodeB];
      node = nodeA;
      while (node = node.parentNode) {
        if (node === nodeB) {
          return 10
        }
        parentsA.push(node)
      }
      node = nodeB;
      while (node = node.parentNode) {
        if (node === nodeA) {
          return 20
        }
        parentsB.push(node)
      }
      parentsA.reverse();
      parentsB.reverse();
      if (parentsA[0] !== parentsB[0]) {
        return 1
      }
      var i = -1;
      while (i++, parentsA[i] === parentsB[i]) {
      }
      nodeA = parentsA[i];
      nodeB = parentsB[i];
      while (nodeA = nodeA.nextSibling) {
        if (nodeA === nodeB) {
          return 4
        }
      }
      return 2
    },
    getNodeIndex: function (node, ignoreTextNode) {
      var preNode = node, i = 0;
      while (preNode = preNode.previousSibling) {
        if (ignoreTextNode && preNode.nodeType == 3) {
          if (preNode.nodeType != preNode.nextSibling.nodeType) {
            i++
          }
          continue
        }
        i++
      }
      return i
    },
    inDoc: function (node, doc) {
      return domUtils.getPosition(node, doc) === 10
    },
    findParent: function (node, filterFn, includeSelf) {
      if (node && !domUtils.isBody(node)) {
        node = includeSelf ? node : node.parentNode;
        while (node) {
          if (!filterFn || filterFn(node) || domUtils.isBody(node)) {
            return filterFn && !filterFn(node) && domUtils.isBody(node) ? null : node
          }
          node = node.parentNode
        }
      }
      return null
    },
    findParentByTagName: function (node, tagNames, includeSelf, excludeFn) {
      tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]);
      return domUtils.findParent(node, function (node) {
        return tagNames[node.tagName] && !(excludeFn && excludeFn(node))
      }, includeSelf)
    },
    findParents: function (node, includeSelf, filterFn, closerFirst) {
      var parents = includeSelf && (filterFn && filterFn(node) || !filterFn) ? [node] : [];
      while (node = domUtils.findParent(node, filterFn)) {
        parents.push(node)
      }
      return closerFirst ? parents : parents.reverse()
    },
    insertAfter: function (node, newNode) {
      return node.nextSibling ? node.parentNode.insertBefore(newNode, node.nextSibling) : node.parentNode.appendChild(newNode)
    },
    remove: function (node, keepChildren) {
      var parent = node.parentNode, child;
      if (parent) {
        if (keepChildren && node.hasChildNodes()) {
          while (child = node.firstChild) {
            parent.insertBefore(child, node)
          }
        }
        parent.removeChild(node)
      }
      return node
    },
    getNextDomNode: function (node, startFromChild, filterFn, guard) {
      return getDomNode(node, "firstChild", "nextSibling", startFromChild, filterFn, guard)
    },
    getPreDomNode: function (node, startFromChild, filterFn, guard) {
      return getDomNode(node, "lastChild", "previousSibling", startFromChild, filterFn, guard)
    },
    isBookmarkNode: function (node) {
      return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id)
    },
    getWindow: function (node) {
      var doc = node.ownerDocument || node;
      return doc.defaultView || doc.parentWindow
    },
    getCommonAncestor: function (nodeA, nodeB) {
      if (nodeA === nodeB) return nodeA;
      var parentsA = [nodeA], parentsB = [nodeB], parent = nodeA, i = -1;
      while (parent = parent.parentNode) {
        if (parent === nodeB) {
          return parent
        }
        parentsA.push(parent)
      }
      parent = nodeB;
      while (parent = parent.parentNode) {
        if (parent === nodeA) return parent;
        parentsB.push(parent)
      }
      parentsA.reverse();
      parentsB.reverse();
      while (i++, parentsA[i] === parentsB[i]) {
      }
      return i == 0 ? null : parentsA[i - 1]
    },
    clearEmptySibling: function (node, ignoreNext, ignorePre) {
      function clear(next, dir) {
        var tmpNode;
        while (next && !domUtils.isBookmarkNode(next) && (domUtils.isEmptyInlineElement(next) || !new RegExp("[^\t\n\r" + domUtils.fillChar + "]").test(next.nodeValue))) {
          tmpNode = next[dir];
          domUtils.remove(next);
          next = tmpNode
        }
      }

      !ignoreNext && clear(node.nextSibling, "nextSibling");
      !ignorePre && clear(node.previousSibling, "previousSibling")
    },
    split: function (node, offset) {
      var doc = node.ownerDocument;
      if (browser.ie && offset == node.nodeValue.length) {
        var next = doc.createTextNode("");
        return domUtils.insertAfter(node, next)
      }
      var retval = node.splitText(offset);
      if (browser.ie8) {
        var tmpNode = doc.createTextNode("");
        domUtils.insertAfter(retval, tmpNode);
        domUtils.remove(tmpNode)
      }
      return retval
    },
    isWhitespace: function (node) {
      return !new RegExp("[^ \t\n\r" + domUtils.fillChar + "]").test(node.nodeValue)
    },
    getXY: function (element) {
      var x = 0, y = 0;
      while (element.offsetParent) {
        y += element.offsetTop;
        x += element.offsetLeft;
        element = element.offsetParent
      }
      return {x: x, y: y}
    },
    on: function (element, type, handler) {
      var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), k = types.length;
      if (k) while (k--) {
        type = types[k];
        if (element.addEventListener) {
          element.addEventListener(type, handler, false)
        } else {
          if (!handler._d) {
            handler._d = {els: []}
          }
          var key = type + handler.toString(), index = utils.indexOf(handler._d.els, element);
          if (!handler._d[key] || index == -1) {
            if (index == -1) {
              handler._d.els.push(element)
            }
            if (!handler._d[key]) {
              handler._d[key] = function (evt) {
                return handler.call(evt.srcElement, evt || window.event)
              }
            }
            element.attachEvent("on" + type, handler._d[key])
          }
        }
      }
      element = null
    },
    un: function (element, type, handler) {
      var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), k = types.length;
      if (k) while (k--) {
        type = types[k];
        if (element.removeEventListener) {
          element.removeEventListener(type, handler, false)
        } else {
          var key = type + handler.toString();
          try {
            element.detachEvent("on" + type, handler._d ? handler._d[key] : handler)
          } catch (e) {
          }
          if (handler._d && handler._d[key]) {
            var index = utils.indexOf(handler._d.els, element);
            if (index != -1) {
              handler._d.els.splice(index, 1)
            }
            handler._d.els.length == 0 && delete handler._d[key]
          }
        }
      }
    },
    isSameElement: function (nodeA, nodeB) {
      if (nodeA.tagName != nodeB.tagName) {
        return false
      }
      var thisAttrs = nodeA.attributes, otherAttrs = nodeB.attributes;
      if (!ie && thisAttrs.length != otherAttrs.length) {
        return false
      }
      var attrA, attrB, al = 0, bl = 0;
      for (var i = 0; attrA = thisAttrs[i++];) {
        if (attrA.nodeName == "style") {
          if (attrA.specified) {
            al++
          }
          if (domUtils.isSameStyle(nodeA, nodeB)) {
            continue
          } else {
            return false
          }
        }
        if (ie) {
          if (attrA.specified) {
            al++;
            attrB = otherAttrs.getNamedItem(attrA.nodeName)
          } else {
            continue
          }
        } else {
          attrB = nodeB.attributes[attrA.nodeName]
        }
        if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) {
          return false
        }
      }
      if (ie) {
        for (i = 0; attrB = otherAttrs[i++];) {
          if (attrB.specified) {
            bl++
          }
        }
        if (al != bl) {
          return false
        }
      }
      return true
    },
    isSameStyle: function (nodeA, nodeB) {
      var styleA = nodeA.style.cssText.replace(/( ?; ?)/g, ";").replace(/( ?: ?)/g, ":"), styleB = nodeB.style.cssText.replace(/( ?; ?)/g, ";").replace(/( ?: ?)/g, ":");
      if (browser.opera) {
        styleA = nodeA.style;
        styleB = nodeB.style;
        if (styleA.length != styleB.length) return false;
        for (var p in styleA) {
          if (/^(\d+|csstext)$/i.test(p)) {
            continue
          }
          if (styleA[p] != styleB[p]) {
            return false
          }
        }
        return true
      }
      if (!styleA || !styleB) {
        return styleA == styleB
      }
      styleA = styleA.split(";");
      styleB = styleB.split(";");
      if (styleA.length != styleB.length) {
        return false
      }
      for (var i = 0, ci; ci = styleA[i++];) {
        if (utils.indexOf(styleB, ci) == -1) {
          return false
        }
      }
      return true
    },
    isBlockElm: function (node) {
      return node.nodeType == 1 && (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle(node, "display")]) && !dtd.$nonChild[node.tagName]
    },
    isBody: function (node) {
      return node && node.nodeType == 1 && node.tagName.toLowerCase() == "body"
    },
    breakParent: function (node, parent) {
      var tmpNode, parentClone = node, clone = node, leftNodes, rightNodes;
      do {
        parentClone = parentClone.parentNode;
        if (leftNodes) {
          tmpNode = parentClone.cloneNode(false);
          tmpNode.appendChild(leftNodes);
          leftNodes = tmpNode;
          tmpNode = parentClone.cloneNode(false);
          tmpNode.appendChild(rightNodes);
          rightNodes = tmpNode
        } else {
          leftNodes = parentClone.cloneNode(false);
          rightNodes = leftNodes.cloneNode(false)
        }
        while (tmpNode = clone.previousSibling) {
          leftNodes.insertBefore(tmpNode, leftNodes.firstChild)
        }
        while (tmpNode = clone.nextSibling) {
          rightNodes.appendChild(tmpNode)
        }
        clone = parentClone
      } while (parent !== parentClone);
      tmpNode = parent.parentNode;
      tmpNode.insertBefore(leftNodes, parent);
      tmpNode.insertBefore(rightNodes, parent);
      tmpNode.insertBefore(node, rightNodes);
      domUtils.remove(parent);
      return node
    },
    isEmptyInlineElement: function (node) {
      if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) {
        return 0
      }
      node = node.firstChild;
      while (node) {
        if (domUtils.isBookmarkNode(node)) {
          return 0
        }
        if (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node) || node.nodeType == 3 && !domUtils.isWhitespace(node)) {
          return 0
        }
        node = node.nextSibling
      }
      return 1
    },
    trimWhiteTextNode: function (node) {
      function remove(dir) {
        var child;
        while ((child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace(child)) {
          node.removeChild(child)
        }
      }

      remove("firstChild");
      remove("lastChild")
    },
    mergeChild: function (node, tagName, attrs) {
      var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase());
      for (var i = 0, ci; ci = list[i++];) {
        if (!ci.parentNode || domUtils.isBookmarkNode(ci)) {
          continue
        }
        if (ci.tagName.toLowerCase() == "span") {
          if (node === ci.parentNode) {
            domUtils.trimWhiteTextNode(node);
            if (node.childNodes.length == 1) {
              node.style.cssText = ci.style.cssText + ";" + node.style.cssText;
              domUtils.remove(ci, true);
              continue
            }
          }
          ci.style.cssText = node.style.cssText + ";" + ci.style.cssText;
          if (attrs) {
            var style = attrs.style;
            if (style) {
              style = style.split(";");
              for (var j = 0, s; s = style[j++];) {
                ci.style[utils.cssStyleToDomStyle(s.split(":")[0])] = s.split(":")[1]
              }
            }
          }
          if (domUtils.isSameStyle(ci, node)) {
            domUtils.remove(ci, true)
          }
          continue
        }
        if (domUtils.isSameElement(node, ci)) {
          domUtils.remove(ci, true)
        }
      }
    },
    getElementsByTagName: function (node, tagName, filter) {
      if (filter && utils.isString(filter)) {
        var className = filter;
        filter = function (node) {
          return domUtils.hasClass(node, className)
        }
      }
      tagName = utils.trim(tagName).replace(/[ ]{2,}/g, " ").split(" ");
      var arr = [];
      for (var n = 0, ni; ni = tagName[n++];) {
        var list = node.getElementsByTagName(ni);
        for (var i = 0, ci; ci = list[i++];) {
          if (!filter || filter(ci)) arr.push(ci)
        }
      }
      return arr
    },
    mergeToParent: function (node) {
      var parent = node.parentNode;
      while (parent && dtd.$removeEmpty[parent.tagName]) {
        if (parent.tagName == node.tagName || parent.tagName == "A") {
          domUtils.trimWhiteTextNode(parent);
          if (parent.tagName == "SPAN" && !domUtils.isSameStyle(parent, node) || parent.tagName == "A" && node.tagName == "SPAN") {
            if (parent.childNodes.length > 1 || parent !== node.parentNode) {
              node.style.cssText = parent.style.cssText + ";" + node.style.cssText;
              parent = parent.parentNode;
              continue
            } else {
              parent.style.cssText += ";" + node.style.cssText;
              if (parent.tagName == "A") {
                parent.style.textDecoration = "underline"
              }
            }
          }
          if (parent.tagName != "A") {
            parent === node.parentNode && domUtils.remove(node, true);
            break
          }
        }
        parent = parent.parentNode
      }
    },
    mergeSibling: function (node, ignorePre, ignoreNext) {
      function merge(rtl, start, node) {
        var next;
        if ((next = node[rtl]) && !domUtils.isBookmarkNode(next) && next.nodeType == 1 && domUtils.isSameElement(node, next)) {
          while (next.firstChild) {
            if (start == "firstChild") {
              node.insertBefore(next.lastChild, node.firstChild)
            } else {
              node.appendChild(next.firstChild)
            }
          }
          domUtils.remove(next)
        }
      }

      !ignorePre && merge("previousSibling", "firstChild", node);
      !ignoreNext && merge("nextSibling", "lastChild", node)
    },
    unSelectable: ie && browser.ie9below || browser.opera ? function (node) {
      node.onselectstart = function () {
        return false
      };
      node.onclick = node.onkeyup = node.onkeydown = function () {
        return false
      };
      node.unselectable = "on";
      node.setAttribute("unselectable", "on");
      for (var i = 0, ci; ci = node.all[i++];) {
        switch (ci.tagName.toLowerCase()) {
          case"iframe":
          case"textarea":
          case"input":
          case"select":
            break;
          default:
            ci.unselectable = "on";
            node.setAttribute("unselectable", "on")
        }
      }
    } : function (node) {
      node.style.MozUserSelect = node.style.webkitUserSelect = node.style.msUserSelect = node.style.KhtmlUserSelect = "none"
    },
    removeAttributes: function (node, attrNames) {
      attrNames = utils.isArray(attrNames) ? attrNames : utils.trim(attrNames).replace(/[ ]{2,}/g, " ").split(" ");
      for (var i = 0, ci; ci = attrNames[i++];) {
        ci = attrFix[ci] || ci;
        switch (ci) {
          case"className":
            node[ci] = "";
            break;
          case"style":
            node.style.cssText = "";
            var val = node.getAttributeNode("style");
            !browser.ie && val && node.removeAttributeNode(val)
        }
        node.removeAttribute(ci)
      }
    },
    createElement: function (doc, tag, attrs) {
      return domUtils.setAttributes(doc.createElement(tag), attrs)
    },
    setAttributes: function (node, attrs) {
      for (var attr in attrs) {
        if ("_propertyDelete" === attr) {
          for (var j = 0; j < attrs[attr].length; j++) {
            if (node.hasAttribute(attrs[attr][j])) {
              node.removeAttribute(attrs[attr][j])
            }
          }
          continue
        }
        if (attrs.hasOwnProperty(attr)) {
          var value = attrs[attr];
          switch (attr) {
            case"class":
              node.className = value;
              break;
            case"style":
              node.style.cssText = node.style.cssText + ";" + value;
              break;
            case"innerHTML":
              node[attr] = value;
              break;
            case"value":
              node.value = value;
              break;
            default:
              node.setAttribute(attrFix[attr] || attr, value)
          }
        }
      }
      return node
    },
    getComputedStyle: function (element, styleName) {
      var pros = "width height top left";
      if (pros.indexOf(styleName) > -1) {
        return element["offset" + styleName.replace(/^\w/, function (s) {
          return s.toUpperCase()
        })] + "px"
      }
      if (element.nodeType === 3) {
        element = element.parentNode
      }
      if (browser.ie && browser.version < 9 && styleName === "font-size" && !element.style.fontSize && !dtd.$empty[element.tagName] && !dtd.$nonChild[element.tagName]) {
        var span = element.ownerDocument.createElement("span");
        span.style.cssText = "padding:0;border:0;font-family:simsun;";
        span.innerHTML = ".";
        element.appendChild(span);
        var result = span.offsetHeight;
        element.removeChild(span);
        span = null;
        return result + "px"
      }
      try {
        var value = domUtils.getStyle(element, styleName) || (window.getComputedStyle ? domUtils.getWindow(element).getComputedStyle(element, "").getPropertyValue(styleName) : (element.currentStyle || element.style)[utils.cssStyleToDomStyle(styleName)])
      } catch (e) {
        return ""
      }
      return utils.transUnitToPx(utils.fixColor(styleName, value))
    },
    removeClasses: function (elm, classNames) {
      classNames = utils.isArray(classNames) ? classNames : utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ");
      for (var i = 0, ci, cls = elm.className; ci = classNames[i++];) {
        cls = cls.replace(new RegExp("\\b" + ci + "\\b"), "")
      }
      cls = utils.trim(cls).replace(/[ ]{2,}/g, " ");
      if (cls) {
        elm.className = cls
      } else {
        domUtils.removeAttributes(elm, ["class"])
      }
    },
    addClass: function (elm, classNames) {
      if (!elm) return;
      classNames = utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ");
      for (var i = 0, ci, cls = elm.className; ci = classNames[i++];) {
        if (!new RegExp("\\b" + ci + "\\b").test(cls)) {
          cls += " " + ci
        }
      }
      elm.className = utils.trim(cls)
    },
    hasClass: function (element, className) {
      if (utils.isRegExp(className)) {
        return className.test(element.className)
      }
      className = utils.trim(className).replace(/[ ]{2,}/g, " ").split(" ");
      for (var i = 0, ci, cls = element.className; ci = className[i++];) {
        if (!new RegExp("\\b" + ci + "\\b", "i").test(cls)) {
          return false
        }
      }
      return i - 1 == className.length
    },
    preventDefault: function (evt) {
      evt.preventDefault ? evt.preventDefault() : evt.returnValue = false
    },
    removeStyle: function (element, name) {
      if (browser.ie) {
        if (name == "color") {
          name = "(^|;)" + name
        }
        element.style.cssText = element.style.cssText.replace(new RegExp(name + "[^:]*:[^;]+;?", "ig"), "")
      } else {
        if (element.style.removeProperty) {
          element.style.removeProperty(name)
        } else {
          element.style.removeAttribute(utils.cssStyleToDomStyle(name))
        }
      }
      if (!element.style.cssText) {
        domUtils.removeAttributes(element, ["style"])
      }
    },
    getStyle: function (element, name) {
      var value = element.style[utils.cssStyleToDomStyle(name)];
      return utils.fixColor(name, value)
    },
    setStyle: function (element, name, value) {
      element.style[utils.cssStyleToDomStyle(name)] = value;
      if (!utils.trim(element.style.cssText)) {
        this.removeAttributes(element, "style")
      }
    },
    setStyles: function (element, styles) {
      for (var name in styles) {
        if (styles.hasOwnProperty(name)) {
          domUtils.setStyle(element, name, styles[name])
        }
      }
    },
    removeDirtyAttr: function (node) {
      for (var i = 0, ci, nodes = node.getElementsByTagName("*"); ci = nodes[i++];) {
        ci.removeAttribute("_moz_dirty")
      }
      node.removeAttribute("_moz_dirty")
    },
    getChildCount: function (node, fn) {
      var count = 0, first = node.firstChild;
      fn = fn || function () {
        return 1
      };
      while (first) {
        if (fn(first)) {
          count++
        }
        first = first.nextSibling
      }
      return count
    },
    isEmptyNode: function (node) {
      return !node.firstChild || domUtils.getChildCount(node, function (node) {
        return !domUtils.isBr(node) && !domUtils.isBookmarkNode(node) && !domUtils.isWhitespace(node)
      }) == 0
    },
    clearSelectedArr: function (nodes) {
      var node;
      while (node = nodes.pop()) {
        domUtils.removeAttributes(node, ["class"])
      }
    },
    scrollToView: function (node, win, offsetTop) {
      offsetTop = offsetTop || 0;
      var getViewPaneSize = function () {
        var doc = win.document, mode = doc.compatMode == "CSS1Compat";
        return {width: (mode ? doc.documentElement.clientWidth : doc.body.clientWidth) || 0, height: (mode ? doc.documentElement.clientHeight : doc.body.clientHeight) || 0}
      }, getScrollPosition = function (win) {
        if ("pageXOffset" in win) {
          return {x: win.pageXOffset || 0, y: win.pageYOffset || 0}
        } else {
          var doc = win.document;
          return {x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0, y: doc.documentElement.scrollTop || doc.body.scrollTop || 0}
        }
      };
      var winHeight = getViewPaneSize().height, offset = winHeight * -1 + offsetTop;
      offset += node.offsetHeight || 0;
      var elementPosition = domUtils.getXY(node);
      offset += elementPosition.y;
      var currentScroll = getScrollPosition(win).y;
      if (offset > currentScroll || offset < currentScroll - winHeight) {
        win.scrollTo({top: offset + (offset < 0 ? -20 : 20), behavior: "smooth"})
      }
    },
    isBr: function (node) {
      return node.nodeType == 1 && node.tagName == "BR"
    },
    isFillChar: function (node, isInStart) {
      if (node.nodeType != 3) return false;
      var text = node.nodeValue;
      if (isInStart) {
        return new RegExp("^" + domUtils.fillChar).test(text)
      }
      return !text.replace(new RegExp(domUtils.fillChar, "g"), "").length
    },
    isStartInblock: function (range) {
      var tmpRange = range.cloneRange(), flag = 0, start = tmpRange.startContainer, tmp;
      if (start.nodeType == 1 && start.childNodes[tmpRange.startOffset]) {
        start = start.childNodes[tmpRange.startOffset];
        var pre = start.previousSibling;
        while (pre && domUtils.isFillChar(pre)) {
          start = pre;
          pre = pre.previousSibling
        }
      }
      if (this.isFillChar(start, true) && tmpRange.startOffset == 1) {
        tmpRange.setStartBefore(start);
        start = tmpRange.startContainer
      }
      while (start && domUtils.isFillChar(start)) {
        tmp = start;
        start = start.previousSibling
      }
      if (tmp) {
        tmpRange.setStartBefore(tmp);
        start = tmpRange.startContainer
      }
      if (start.nodeType == 1 && domUtils.isEmptyNode(start) && tmpRange.startOffset == 1) {
        tmpRange.setStart(start, 0).collapse(true)
      }
      while (!tmpRange.startOffset) {
        start = tmpRange.startContainer;
        if (domUtils.isBlockElm(start) || domUtils.isBody(start)) {
          flag = 1;
          break
        }
        var pre = tmpRange.startContainer.previousSibling, tmpNode;
        if (!pre) {
          tmpRange.setStartBefore(tmpRange.startContainer)
        } else {
          while (pre && domUtils.isFillChar(pre)) {
            tmpNode = pre;
            pre = pre.previousSibling
          }
          if (tmpNode) {
            tmpRange.setStartBefore(tmpNode)
          } else {
            tmpRange.setStartBefore(tmpRange.startContainer)
          }
        }
      }
      return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0
    },
    isEmptyBlock: function (node, reg) {
      if (node.nodeType != 1) return 0;
      reg = reg || new RegExp("[  \t\r\n" + domUtils.fillChar + "]", "g");
      if (node[browser.ie ? "innerText" : "textContent"].replace(reg, "").length > 0) {
        return 0
      }
      for (var n in dtd.$isNotEmpty) {
        if (node.getElementsByTagName(n).length) {
          return 0
        }
      }
      return 1
    },
    setViewportOffset: function (element, offset) {
      var left = parseInt(element.style.left) | 0;
      var top = parseInt(element.style.top) | 0;
      var rect = element.getBoundingClientRect();
      var offsetLeft = offset.left - rect.left;
      var offsetTop = offset.top - rect.top;
      if (offsetLeft) {
        element.style.left = left + offsetLeft + "px"
      }
      if (offsetTop) {
        element.style.top = top + offsetTop + "px"
      }
    },
    fillNode: function (doc, node) {
      var tmpNode = browser.ie ? doc.createTextNode(domUtils.fillChar) : doc.createElement("br");
      node.innerHTML = "";
      node.appendChild(tmpNode)
    },
    moveChild: function (src, tag, dir) {
      while (src.firstChild) {
        if (dir && tag.firstChild) {
          tag.insertBefore(src.lastChild, tag.firstChild)
        } else {
          tag.appendChild(src.firstChild)
        }
      }
    },
    hasNoAttributes: function (node) {
      return browser.ie ? /^<\w+\s*?>/.test(node.outerHTML) : node.attributes.length == 0
    },
    isCustomeNode: function (node) {
      return node.nodeType == 1 && node.getAttribute("_ue_custom_node_")
    },
    isTagNode: function (node, tagNames) {
      return node.nodeType == 1 && new RegExp("\\b" + node.tagName + "\\b", "i").test(tagNames)
    },
    filterNodeList: function (nodelist, filter, forAll) {
      var results = [];
      if (!utils.isFunction(filter)) {
        var str = filter;
        filter = function (n) {
          return utils.indexOf(utils.isArray(str) ? str : str.split(" "), n.tagName.toLowerCase()) != -1
        }
      }
      utils.each(nodelist, function (n) {
        filter(n) && results.push(n)
      });
      return results.length == 0 ? null : results.length == 1 || !forAll ? results[0] : results
    },
    isInNodeEndBoundary: function (rng, node) {
      var start = rng.startContainer;
      if (start.nodeType == 3 && rng.startOffset != start.nodeValue.length) {
        return 0
      }
      if (start.nodeType == 1 && rng.startOffset != start.childNodes.length) {
        return 0
      }
      while (start !== node) {
        if (start.nextSibling) {
          return 0
        }
        start = start.parentNode
      }
      return 1
    },
    isBoundaryNode: function (node, dir) {
      var tmp;
      while (!domUtils.isBody(node)) {
        tmp = node;
        node = node.parentNode;
        if (tmp !== node[dir]) {
          return false
        }
      }
      return true
    },
    fillHtml: browser.ie11below ? "&nbsp;" : "<br/>",
    loadScript: function (url, cb) {
      var script;
      script = document.createElement("script");
      script.src = url;
      script.onload = function () {
        cb && cb({isNew: true})
      };
      document.getElementsByTagName("head")[0].appendChild(script)
    }
  };
  var fillCharReg = new RegExp(domUtils.fillChar, "g");
  (function () {
    var guid = 0, fillChar = domUtils.fillChar, fillData;

    function updateCollapse(range) {
      range.collapsed = range.startContainer && range.endContainer && range.startContainer === range.endContainer && range.startOffset === range.endOffset
    }

    function selectOneNode(rng) {
      return !rng.collapsed && rng.startContainer.nodeType === 1 && rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset === 1
    }

    function setEndPoint(toStart, node, offset, range) {
      if (node.nodeType === 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName])) {
        offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1);
        node = node.parentNode
      }
      if (toStart) {
        range.startContainer = node;
        range.startOffset = offset;
        if (!range.endContainer) {
          range.collapse(true)
        }
      } else {
        range.endContainer = node;
        range.endOffset = offset;
        if (!range.startContainer) {
          range.collapse(false)
        }
      }
      updateCollapse(range);
      return range
    }

    function execContentsAction(range, action) {
      var start = range.startContainer, end = range.endContainer, startOffset = range.startOffset, endOffset = range.endOffset, doc = range.document, frag = doc.createDocumentFragment(), tmpStart, tmpEnd;
      if (start.nodeType == 1) {
        start = start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode("")))
      }
      if (end.nodeType == 1) {
        end = end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode("")))
      }
      if (start === end && start.nodeType == 3) {
        frag.appendChild(doc.createTextNode(start.substringData(startOffset, endOffset - startOffset)));
        if (action) {
          start.deleteData(startOffset, endOffset - startOffset);
          range.collapse(true)
        }
        return frag
      }
      var current, currentLevel, clone = frag, startParents = domUtils.findParents(start, true), endParents = domUtils.findParents(end, true);
      for (var i = 0; startParents[i] == endParents[i];) {
        i++
      }
      for (var j = i, si; si = startParents[j]; j++) {
        current = si.nextSibling;
        if (si == start) {
          if (!tmpStart) {
            if (range.startContainer.nodeType == 3) {
              clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset)));
              if (action) {
                start.deleteData(startOffset, start.nodeValue.length - startOffset)
              }
            } else {
              clone.appendChild(!action ? start.cloneNode(true) : start)
            }
          }
        } else {
          currentLevel = si.cloneNode(false);
          clone.appendChild(currentLevel)
        }
        while (current) {
          if (current === end || current === endParents[j]) {
            break
          }
          si = current.nextSibling;
          clone.appendChild(!action ? current.cloneNode(true) : current);
          current = si
        }
        clone = currentLevel
      }
      clone = frag;
      if (!startParents[i]) {
        clone.appendChild(startParents[i - 1].cloneNode(false));
        clone = clone.firstChild
      }
      for (var j = i, ei; ei = endParents[j]; j++) {
        current = ei.previousSibling;
        if (ei == end) {
          if (!tmpEnd && range.endContainer.nodeType == 3) {
            clone.appendChild(doc.createTextNode(end.substringData(0, endOffset)));
            if (action) {
              end.deleteData(0, endOffset)
            }
          }
        } else {
          currentLevel = ei.cloneNode(false);
          clone.appendChild(currentLevel)
        }
        if (j != i || !startParents[i]) {
          while (current) {
            if (current === start) {
              break
            }
            ei = current.previousSibling;
            clone.insertBefore(!action ? current.cloneNode(true) : current, clone.firstChild);
            current = ei
          }
        }
        clone = currentLevel
      }
      if (action) {
        range.setStartBefore(!endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i]).collapse(true)
      }
      tmpStart && domUtils.remove(tmpStart);
      tmpEnd && domUtils.remove(tmpEnd);
      return frag
    }

    var Range = dom.Range = function (document) {
      var me = this;
      me.startContainer = me.startOffset = me.endContainer = me.endOffset = null;
      me.document = document;
      me.collapsed = true
    };

    function removeFillData(doc, excludeNode) {
      try {
        if (fillData && domUtils.inDoc(fillData, doc)) {
          if (!fillData.nodeValue.replace(fillCharReg, "").length) {
            var tmpNode = fillData.parentNode;
            domUtils.remove(fillData);
            while (tmpNode && domUtils.isEmptyInlineElement(tmpNode) && (browser.safari ? !(domUtils.getPosition(tmpNode, excludeNode) & domUtils.POSITION_CONTAINS) : !tmpNode.contains(excludeNode))) {
              fillData = tmpNode.parentNode;
              domUtils.remove(tmpNode);
              tmpNode = fillData
            }
          } else {
            fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, "")
          }
        }
      } catch (e) {
      }
    }

    function mergeSibling(node, dir) {
      var tmpNode;
      node = node[dir];
      while (node && domUtils.isFillChar(node)) {
        tmpNode = node[dir];
        domUtils.remove(node);
        node = tmpNode
      }
    }

    Range.prototype = {
      cloneContents: function () {
        return this.collapsed ? null : execContentsAction(this, 0)
      }, deleteContents: function () {
        var txt;
        if (!this.collapsed) {
          execContentsAction(this, 1)
        }
        if (browser.webkit) {
          txt = this.startContainer;
          if (txt.nodeType == 3 && !txt.nodeValue.length) {
            this.setStartBefore(txt).collapse(true);
            domUtils.remove(txt)
          }
        }
        return this
      }, extractContents: function () {
        return this.collapsed ? null : execContentsAction(this, 2)
      }, setStart: function (node, offset) {
        return setEndPoint(true, node, offset, this)
      }, setEnd: function (node, offset) {
        return setEndPoint(false, node, offset, this)
      }, setStartAfter: function (node) {
        return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1)
      }, setStartBefore: function (node) {
        return this.setStart(node.parentNode, domUtils.getNodeIndex(node))
      }, setEndAfter: function (node) {
        return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1)
      }, setEndBefore: function (node) {
        return this.setEnd(node.parentNode, domUtils.getNodeIndex(node))
      }, setStartAtFirst: function (node) {
        return this.setStart(node, 0)
      }, setStartAtLast: function (node) {
        return this.setStart(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length)
      }, setEndAtFirst: function (node) {
        return this.setEnd(node, 0)
      }, setEndAtLast: function (node) {
        return this.setEnd(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length)
      }, selectNode: function (node) {
        return this.setStartBefore(node).setEndAfter(node)
      }, selectNodeContents: function (node) {
        return this.setStart(node, 0).setEndAtLast(node)
      }, cloneRange: function () {
        var me = this;
        return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset)
      }, collapse: function (toStart) {
        var me = this;
        if (toStart) {
          me.endContainer = me.startContainer;
          me.endOffset = me.startOffset
        } else {
          me.startContainer = me.endContainer;
          me.startOffset = me.endOffset
        }
        me.collapsed = true;
        return me
      }, shrinkBoundary: function (ignoreEnd) {
        var me = this, child, collapsed = me.collapsed;

        function check(node) {
          return node.nodeType == 1 && !domUtils.isBookmarkNode(node) && !dtd.$empty[node.tagName] && !dtd.$nonChild[node.tagName]
        }

        while (me.startContainer.nodeType == 1 && (child = me.startContainer.childNodes[me.startOffset]) && check(child)) {
          me.setStart(child, 0)
        }
        if (collapsed) {
          return me.collapse(true)
        }
        if (!ignoreEnd) {
          while (me.endContainer.nodeType == 1 && me.endOffset > 0 && (child = me.endContainer.childNodes[me.endOffset - 1]) && check(child)) {
            me.setEnd(child, child.childNodes.length)
          }
        }
        return me
      }, getCommonAncestor: function (includeSelf, ignoreTextNode) {
        var me = this, start = me.startContainer, end = me.endContainer;
        if (start === end) {
          if (includeSelf && selectOneNode(this)) {
            start = start.childNodes[me.startOffset];
            if (start.nodeType == 1) return start
          }
          return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start
        }
        return domUtils.getCommonAncestor(start, end)
      }, trimBoundary: function (ignoreEnd) {
        this.txtToElmBoundary();
        var start = this.startContainer, offset = this.startOffset, collapsed = this.collapsed, end = this.endContainer;
        if (start.nodeType == 3) {
          if (offset == 0) {
            this.setStartBefore(start)
          } else {
            if (offset >= start.nodeValue.length) {
              this.setStartAfter(start)
            } else {
              var textNode = domUtils.split(start, offset);
              if (start === end) {
                this.setEnd(textNode, this.endOffset - offset)
              } else if (start.parentNode === end) {
                this.endOffset += 1
              }
              this.setStartBefore(textNode)
            }
          }
          if (collapsed) {
            return this.collapse(true)
          }
        }
        if (!ignoreEnd) {
          offset = this.endOffset;
          end = this.endContainer;
          if (end.nodeType == 3) {
            if (offset == 0) {
              this.setEndBefore(end)
            } else {
              offset < end.nodeValue.length && domUtils.split(end, offset);
              this.setEndAfter(end)
            }
          }
        }
        return this
      }, txtToElmBoundary: function (ignoreCollapsed) {
        function adjust(r, c) {
          var container = r[c + "Container"], offset = r[c + "Offset"];
          if (container.nodeType == 3) {
            if (!offset) {
              r["set" + c.replace(/(\w)/, function (a) {
                return a.toUpperCase()
              }) + "Before"](container)
            } else if (offset >= container.nodeValue.length) {
              r["set" + c.replace(/(\w)/, function (a) {
                return a.toUpperCase()
              }) + "After"](container)
            }
          }
        }

        if (ignoreCollapsed || !this.collapsed) {
          adjust(this, "start");
          adjust(this, "end")
        }
        return this
      }, insertNode: function (node) {
        var first = node, length = 1;
        if (node.nodeType == 11) {
          first = node.firstChild;
          length = node.childNodes.length
        }
        this.trimBoundary(true);
        var start = this.startContainer, offset = this.startOffset;
        var nextNode = start.childNodes[offset];
        if (nextNode) {
          start.insertBefore(node, nextNode)
        } else {
          start.appendChild(node)
        }
        if (first.parentNode === this.endContainer) {
          this.endOffset = this.endOffset + length
        }
        return this.setStartBefore(first)
      }, setCursor: function (toEnd, noFillData) {
        return this.collapse(!toEnd).select(noFillData)
      }, createBookmark: function (serialize, same) {
        var endNode, startNode = this.document.createElement("span");
        startNode.style.cssText = "display:none;line-height:0px;";
        startNode.appendChild(this.document.createTextNode("‍"));
        startNode.id = "_baidu_bookmark_start_" + (same ? "" : guid++);
        if (!this.collapsed) {
          endNode = startNode.cloneNode(true);
          endNode.id = "_baidu_bookmark_end_" + (same ? "" : guid++)
        }
        this.insertNode(startNode);
        if (endNode) {
          this.collapse().insertNode(endNode).setEndBefore(endNode)
        }
        this.setStartAfter(startNode);
        return {start: serialize ? startNode.id : startNode, end: endNode ? serialize ? endNode.id : endNode : null, id: serialize}
      }, moveToBookmark: function (bookmark) {
        var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start, end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;
        this.setStartBefore(start);
        domUtils.remove(start);
        if (end) {
          this.setEndBefore(end);
          domUtils.remove(end)
        } else {
          this.collapse(true)
        }
        return this
      }, enlarge: function (toBlock, stopFn) {
        var isBody = domUtils.isBody, pre, node, tmp = this.document.createTextNode("");
        if (toBlock) {
          node = this.startContainer;
          if (node.nodeType == 1) {
            if (node.childNodes[this.startOffset]) {
              pre = node = node.childNodes[this.startOffset]
            } else {
              node.appendChild(tmp);
              pre = node = tmp
            }
          } else {
            pre = node
          }
          while (1) {
            if (domUtils.isBlockElm(node)) {
              node = pre;
              while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) {
                node = pre
              }
              this.setStartBefore(node);
              break
            }
            pre = node;
            node = node.parentNode
          }
          node = this.endContainer;
          if (node.nodeType == 1) {
            if (pre = node.childNodes[this.endOffset]) {
              node.insertBefore(tmp, pre)
            } else {
              node.appendChild(tmp)
            }
            pre = node = tmp
          } else {
            pre = node
          }
          while (1) {
            if (domUtils.isBlockElm(node)) {
              node = pre;
              while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) {
                node = pre
              }
              this.setEndAfter(node);
              break
            }
            pre = node;
            node = node.parentNode
          }
          if (tmp.parentNode === this.endContainer) {
            this.endOffset--
          }
          domUtils.remove(tmp)
        }
        if (!this.collapsed) {
          while (this.startOffset == 0) {
            if (stopFn && stopFn(this.startContainer)) {
              break
            }
            if (isBody(this.startContainer)) {
              break
            }
            this.setStartBefore(this.startContainer)
          }
          while (this.endOffset == (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length)) {
            if (stopFn && stopFn(this.endContainer)) {
              break
            }
            if (isBody(this.endContainer)) {
              break
            }
            this.setEndAfter(this.endContainer)
          }
        }
        return this
      }, enlargeToBlockElm: function (ignoreEnd) {
        while (!domUtils.isBlockElm(this.startContainer)) {
          this.setStartBefore(this.startContainer)
        }
        if (!ignoreEnd) {
          while (!domUtils.isBlockElm(this.endContainer)) {
            this.setEndAfter(this.endContainer)
          }
        }
        return this
      }, adjustmentBoundary: function () {
        if (!this.collapsed) {
          while (!domUtils.isBody(this.startContainer) && this.startOffset == this.startContainer[this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length && this.startContainer[this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
            this.setStartAfter(this.startContainer)
          }
          while (!domUtils.isBody(this.endContainer) && !this.endOffset && this.endContainer[this.endContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
            this.setEndBefore(this.endContainer)
          }
        }
        return this
      }, applyInlineStyle: function (tagName, attrs, list) {
        if (this.collapsed) return this;
        this.trimBoundary().enlarge(false, function (node) {
          return node.nodeType == 1 && domUtils.isBlockElm(node)
        }).adjustmentBoundary();
        var bookmark = this.createBookmark(), end = bookmark.end, filterFn = function (node) {
          return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" : !domUtils.isWhitespace(node)
        }, current = domUtils.getNextDomNode(bookmark.start, false, filterFn), node, pre, range = this.cloneRange();
        while (current && domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING) {
          if (current.nodeType == 3 || dtd[tagName][current.tagName]) {
            range.setStartBefore(current);
            node = current;
            while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) {
              pre = node;
              node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function (parent) {
                return dtd[tagName][parent.tagName]
              })
            }
            var frag = range.setEndAfter(pre).extractContents(), elm;
            if (list && list.length > 0) {
              var level, top;
              top = level = list[0].cloneNode(false);
              for (var i = 1, ci; ci = list[i++];) {
                level.appendChild(ci.cloneNode(false));
                level = level.firstChild
              }
              elm = level
            } else {
              elm = range.document.createElement(tagName)
            }
            if (attrs) {
              domUtils.setAttributes(elm, attrs)
            }
            elm.appendChild(frag);
            if (elm.tagName == "SPAN" && attrs && attrs.style) {
              utils.each(elm.getElementsByTagName("span"), function (s) {
                s.style.cssText = s.style.cssText + ";" + attrs.style
              })
            }
            range.insertNode(list ? top : elm);
            var aNode;
            if (tagName == "span" && attrs.style && /text\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, "a", true))) {
              domUtils.setAttributes(aNode, attrs);
              domUtils.remove(elm, true);
              elm = aNode
            } else {
              domUtils.mergeSibling(elm);
              domUtils.clearEmptySibling(elm)
            }
            domUtils.mergeChild(elm, attrs);
            current = domUtils.getNextDomNode(elm, false, filterFn);
            domUtils.mergeToParent(elm);
            if (node === end) {
              break
            }
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn)
          }
        }
        return this.moveToBookmark(bookmark)
      }, removeInlineStyle: function (tagNames) {
        if (this.collapsed) return this;
        tagNames = utils.isArray(tagNames) ? tagNames : [tagNames];
        this.shrinkBoundary().adjustmentBoundary();
        var start = this.startContainer, end = this.endContainer;
        while (1) {
          if (start.nodeType == 1) {
            if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) {
              break
            }
            if (start.tagName.toLowerCase() == "body") {
              start = null;
              break
            }
          }
          start = start.parentNode
        }
        while (1) {
          if (end.nodeType == 1) {
            if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) {
              break
            }
            if (end.tagName.toLowerCase() == "body") {
              end = null;
              break
            }
          }
          end = end.parentNode
        }
        var bookmark = this.createBookmark(), frag, tmpRange;
        if (start) {
          tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start);
          frag = tmpRange.extractContents();
          tmpRange.insertNode(frag);
          domUtils.clearEmptySibling(start, true);
          start.parentNode.insertBefore(bookmark.start, start)
        }
        if (end) {
          tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end);
          frag = tmpRange.extractContents();
          tmpRange.insertNode(frag);
          domUtils.clearEmptySibling(end, false, true);
          end.parentNode.insertBefore(bookmark.end, end.nextSibling)
        }
        var current = domUtils.getNextDomNode(bookmark.start, false, function (node) {
          return node.nodeType == 1
        }), next;
        while (current && current !== bookmark.end) {
          next = domUtils.getNextDomNode(current, true, function (node) {
            return node.nodeType == 1
          });
          if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) {
            domUtils.remove(current, true)
          }
          current = next
        }
        return this.moveToBookmark(bookmark)
      }, getClosedNode: function () {
        var node;
        if (!this.collapsed) {
          var range = this.cloneRange().adjustmentBoundary().shrinkBoundary();
          if (selectOneNode(range)) {
            var child = range.startContainer.childNodes[range.startOffset];
            if (child && child.nodeType === 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) {
              node = child
            }
          }
        }
        return node
      }, select: browser.ie ? function (noFillData, textRange) {
        var nativeRange;
        if (!this.collapsed) this.shrinkBoundary();
        var node = this.getClosedNode();
        if (node && !textRange) {
          try {
            nativeRange = this.document.body.createControlRange();
            nativeRange.addElement(node);
            nativeRange.select()
          } catch (e) {
          }
          return this
        }
        var bookmark = this.createBookmark(), start = bookmark.start, end;
        nativeRange = this.document.body.createTextRange();
        nativeRange.moveToElementText(start);
        nativeRange.moveStart("character", 1);
        if (!this.collapsed) {
          var nativeRangeEnd = this.document.body.createTextRange();
          end = bookmark.end;
          nativeRangeEnd.moveToElementText(end);
          nativeRange.setEndPoint("EndToEnd", nativeRangeEnd)
        } else {
          if (!noFillData && this.startContainer.nodeType != 3) {
            var tmpText = this.document.createTextNode(fillChar), tmp = this.document.createElement("span");
            tmp.appendChild(this.document.createTextNode(fillChar));
            start.parentNode.insertBefore(tmp, start);
            start.parentNode.insertBefore(tmpText, start);
            removeFillData(this.document, tmpText);
            fillData = tmpText;
            mergeSibling(tmp, "previousSibling");
            mergeSibling(start, "nextSibling");
            nativeRange.moveStart("character", -1);
            nativeRange.collapse(true)
          }
        }
        this.moveToBookmark(bookmark);
        tmp && domUtils.remove(tmp);
        try {
          nativeRange.select()
        } catch (e) {
        }
        return this
      } : function (notInsertFillData) {
        function checkOffset(rng) {
          function check(node, offset, dir) {
            if (node.nodeType == 3 && node.nodeValue.length < offset) {
              rng[dir + "Offset"] = node.nodeValue.length
            }
          }

          check(rng.startContainer, rng.startOffset, "start");
          check(rng.endContainer, rng.endOffset, "end")
        }

        var win = domUtils.getWindow(this.document), sel = win.getSelection(), txtNode;
        browser.gecko ? this.document.body.focus() : win.focus();
        if (sel) {
          sel.removeAllRanges();
          if (this.collapsed && !notInsertFillData) {
            var start = this.startContainer, child = start;
            if (start.nodeType == 1) {
              child = start.childNodes[this.startOffset]
            }
            if (!(start.nodeType == 3 && this.startOffset) && (child ? !child.previousSibling || child.previousSibling.nodeType != 3 : !start.lastChild || start.lastChild.nodeType != 3)) {
              txtNode = this.document.createTextNode(fillChar);
              this.insertNode(txtNode);
              removeFillData(this.document, txtNode);
              mergeSibling(txtNode, "previousSibling");
              mergeSibling(txtNode, "nextSibling");
              fillData = txtNode;
              this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true)
            }
          }
          var nativeRange = this.document.createRange();
          if (this.collapsed && browser.opera && this.startContainer.nodeType == 1) {
            var child = this.startContainer.childNodes[this.startOffset];
            if (!child) {
              child = this.startContainer.lastChild;
              if (child && domUtils.isBr(child)) {
                this.setStartBefore(child).collapse(true)
              }
            } else {
              while (child && domUtils.isBlockElm(child)) {
                if (child.nodeType == 1 && child.childNodes[0]) {
                  child = child.childNodes[0]
                } else {
                  break
                }
              }
              child && this.setStartBefore(child).collapse(true)
            }
          }
          checkOffset(this);
          nativeRange.setStart(this.startContainer, this.startOffset);
          nativeRange.setEnd(this.endContainer, this.endOffset);
          sel.addRange(nativeRange)
        }
        return this
      }, scrollToView: function (win, offset) {
        win = win ? window : domUtils.getWindow(this.document);
        offset = offset || win.innerHeight - 100;
        var me = this, span = me.document.createElement("span");
        span.innerHTML = "&nbsp;";
        me.cloneRange().insertNode(span);
        domUtils.scrollToView(span, win, offset);
        domUtils.remove(span);
        return me
      }, inFillChar: function () {
        var start = this.startContainer;
        if (this.collapsed && start.nodeType == 3 && start.nodeValue.replace(new RegExp("^" + domUtils.fillChar), "").length + 1 == start.nodeValue.length) {
          return true
        }
        return false
      }, createAddress: function (ignoreEnd, ignoreTxt) {
        var addr = {}, me = this;

        function getAddress(isStart) {
          var node = isStart ? me.startContainer : me.endContainer;
          var parents = domUtils.findParents(node, true, function (node) {
            return !domUtils.isBody(node)
          }), addrs = [];
          for (var i = 0, ci; ci = parents[i++];) {
            addrs.push(domUtils.getNodeIndex(ci, ignoreTxt))
          }
          var firstIndex = 0;
          if (ignoreTxt) {
            if (node.nodeType == 3) {
              var tmpNode = node.previousSibling;
              while (tmpNode && tmpNode.nodeType == 3) {
                firstIndex += tmpNode.nodeValue.replace(fillCharReg, "").length;
                tmpNode = tmpNode.previousSibling
              }
              firstIndex += isStart ? me.startOffset : me.endOffset
            } else {
              node = node.childNodes[isStart ? me.startOffset : me.endOffset];
              if (node) {
                firstIndex = domUtils.getNodeIndex(node, ignoreTxt)
              } else {
                node = isStart ? me.startContainer : me.endContainer;
                var first = node.firstChild;
                while (first) {
                  if (domUtils.isFillChar(first)) {
                    first = first.nextSibling;
                    continue
                  }
                  firstIndex++;
                  if (first.nodeType == 3) {
                    while (first && first.nodeType == 3) {
                      first = first.nextSibling
                    }
                  } else {
                    first = first.nextSibling
                  }
                }
              }
            }
          } else {
            firstIndex = isStart ? domUtils.isFillChar(node) ? 0 : me.startOffset : me.endOffset
          }
          if (firstIndex < 0) {
            firstIndex = 0
          }
          addrs.push(firstIndex);
          return addrs
        }

        addr.startAddress = getAddress(true);
        if (!ignoreEnd) {
          addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress()
        }
        return addr
      }, moveToAddress: function (addr, ignoreEnd) {
        var me = this;

        function getNode(address, isStart) {
          var tmpNode = me.document.body, parentNode, offset;
          for (var i = 0, ci, l = address.length; i < l; i++) {
            ci = address[i];
            parentNode = tmpNode;
            tmpNode = tmpNode.childNodes[ci];
            if (!tmpNode) {
              offset = ci;
              break
            }
          }
          if (isStart) {
            if (tmpNode) {
              me.setStartBefore(tmpNode)
            } else {
              me.setStart(parentNode, offset)
            }
          } else {
            if (tmpNode) {
              me.setEndBefore(tmpNode)
            } else {
              me.setEnd(parentNode, offset)
            }
          }
        }

        getNode(addr.startAddress, true);
        !ignoreEnd && addr.endAddress && getNode(addr.endAddress);
        return me
      }, equals: function (rng) {
        for (var p in this) {
          if (this.hasOwnProperty(p)) {
            if (this[p] !== rng[p]) return false
          }
        }
        return true
      }, traversal: function (doFn, filterFn) {
        if (this.collapsed) return this;
        var bookmark = this.createBookmark(), end = bookmark.end, current = domUtils.getNextDomNode(bookmark.start, false, filterFn);
        while (current && current !== end && domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING) {
          var tmpNode = domUtils.getNextDomNode(current, false, filterFn);
          doFn(current);
          current = tmpNode
        }
        return this.moveToBookmark(bookmark)
      }
    }
  })();
  (function () {
    function getBoundaryInformation(range, start) {
      var getIndex = domUtils.getNodeIndex;
      range = range.duplicate();
      range.collapse(start);
      var parent = range.parentElement();
      if (!parent.hasChildNodes()) {
        return {container: parent, offset: 0}
      }
      var siblings = parent.children, child, testRange = range.duplicate(), startIndex = 0, endIndex = siblings.length - 1, index = -1, distance;
      while (startIndex <= endIndex) {
        index = Math.floor((startIndex + endIndex) / 2);
        child = siblings[index];
        testRange.moveToElementText(child);
        var position = testRange.compareEndPoints("StartToStart", range);
        if (position > 0) {
          endIndex = index - 1
        } else if (position < 0) {
          startIndex = index + 1
        } else {
          return {container: parent, offset: getIndex(child)}
        }
      }
      if (index == -1) {
        testRange.moveToElementText(parent);
        testRange.setEndPoint("StartToStart", range);
        distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length;
        siblings = parent.childNodes;
        if (!distance) {
          child = siblings[siblings.length - 1];
          return {container: child, offset: child.nodeValue.length}
        }
        var i = siblings.length;
        while (distance > 0) {
          distance -= siblings[--i].nodeValue.length
        }
        return {container: siblings[i], offset: -distance}
      }
      testRange.collapse(position > 0);
      testRange.setEndPoint(position > 0 ? "StartToStart" : "EndToStart", range);
      distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length;
      if (!distance) {
        return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] ? {container: parent, offset: getIndex(child) + (position > 0 ? 0 : 1)} : {container: child, offset: position > 0 ? 0 : child.childNodes.length}
      }
      while (distance > 0) {
        try {
          var pre = child;
          child = child[position > 0 ? "previousSibling" : "nextSibling"];
          distance -= child.nodeValue.length
        } catch (e) {
          return {container: parent, offset: getIndex(pre)}
        }
      }
      return {container: child, offset: position > 0 ? -distance : child.nodeValue.length + distance}
    }

    function transformIERangeToRange(ieRange, range) {
      if (ieRange.item) {
        range.selectNode(ieRange.item(0))
      } else {
        var bi = getBoundaryInformation(ieRange, true);
        range.setStart(bi.container, bi.offset);
        if (ieRange.compareEndPoints("StartToEnd", ieRange) != 0) {
          bi = getBoundaryInformation(ieRange, false);
          range.setEnd(bi.container, bi.offset)
        }
      }
      return range
    }

    function _getIERange(sel) {
      var ieRange;
      try {
        ieRange = sel.getNative().createRange()
      } catch (e) {
        return null
      }
      var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
      if ((el.ownerDocument || el) === sel.document) {
        return ieRange
      }
      return null
    }

    var Selection = dom.Selection = function (doc) {
      var me = this, iframe;
      me.document = doc;
      if (browser.ie9below) {
        iframe = domUtils.getWindow(doc).frameElement;
        domUtils.on(iframe, "beforedeactivate", function () {
          me._bakIERange = me.getIERange()
        });
        domUtils.on(iframe, "activate", function () {
          try {
            if (!_getIERange(me) && me._bakIERange) {
              me._bakIERange.select()
            }
          } catch (ex) {
          }
          me._bakIERange = null
        })
      }
      iframe = doc = null
    };
    Selection.prototype = {
      rangeInBody: function (rng, txtRange) {
        var node = browser.ie9below || txtRange ? rng.item ? rng.item() : rng.parentElement() : rng.startContainer;
        return node === this.document.body || domUtils.inDoc(node, this.document)
      }, getNative: function () {
        var doc = this.document;
        try {
          return !doc ? null : browser.ie9below ? doc.selection : domUtils.getWindow(doc).getSelection()
        } catch (e) {
          return null
        }
      }, getIERange: function () {
        var ieRange = _getIERange(this);
        if (!ieRange) {
          if (this._bakIERange) {
            return this._bakIERange
          }
        }
        return ieRange
      }, cache: function () {
        this.clear();
        this._cachedRange = this.getRange();
        this._cachedStartElement = this.getStart();
        this._cachedStartElementPath = this.getStartElementPath()
      }, getStartElementPath: function () {
        if (this._cachedStartElementPath) {
          return this._cachedStartElementPath
        }
        var start = this.getStart();
        if (start) {
          return domUtils.findParents(start, true, null, true)
        }
        return []
      }, clear: function () {
        this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null
      }, isFocus: function () {
        try {
          if (browser.ie9below) {
            var nativeRange = _getIERange(this);
            return !!(nativeRange && this.rangeInBody(nativeRange))
          } else {
            return !!this.getNative().rangeCount
          }
        } catch (e) {
          return false
        }
      }, getRange: function () {
        var me = this;

        function optimze(range) {
          var child = me.document.body.firstChild, collapsed = range.collapsed;
          while (child && child.firstChild) {
            range.setStart(child, 0);
            child = child.firstChild
          }
          if (!range.startContainer) {
            range.setStart(me.document.body, 0)
          }
          if (collapsed) {
            range.collapse(true)
          }
        }

        if (me._cachedRange != null) {
          return this._cachedRange
        }
        var range = new baidu.editor.dom.Range(me.document);
        if (browser.ie9below) {
          var nativeRange = me.getIERange();
          if (nativeRange) {
            try {
              transformIERangeToRange(nativeRange, range)
            } catch (e) {
              optimze(range)
            }
          } else {
            optimze(range)
          }
        } else {
          var sel = me.getNative();
          if (sel && sel.rangeCount) {
            var firstRange = sel.getRangeAt(0);
            var lastRange = sel.getRangeAt(sel.rangeCount - 1);
            range.setStart(firstRange.startContainer, firstRange.startOffset).setEnd(lastRange.endContainer, lastRange.endOffset);
            if (range.collapsed && domUtils.isBody(range.startContainer) && !range.startOffset) {
              optimze(range)
            }
          } else {
            if (this._bakRange && domUtils.inDoc(this._bakRange.startContainer, this.document)) {
              return this._bakRange
            }
            optimze(range)
          }
        }
        return this._bakRange = range
      }, getStart: function () {
        if (this._cachedStartElement) {
          return this._cachedStartElement
        }
        var range = browser.ie9below ? this.getIERange() : this.getRange(), tmpRange, start, tmp, parent;
        if (browser.ie9below) {
          if (!range) {
            return this.document.body.firstChild
          }
          if (range.item) {
            return range.item(0)
          }
          tmpRange = range.duplicate();
          tmpRange.text.length > 0 && tmpRange.moveStart("character", 1);
          tmpRange.collapse(1);
          start = tmpRange.parentElement();
          parent = tmp = range.parentElement();
          while (tmp = tmp.parentNode) {
            if (tmp == start) {
              start = parent;
              break
            }
          }
        } else {
          range.shrinkBoundary();
          start = range.startContainer;
          if (start.nodeType == 1 && start.hasChildNodes()) {
            start = start.childNodes[Math.min(start.childNodes.length - 1, range.startOffset)]
          }
          if (start.nodeType == 3) {
            return start.parentNode
          }
        }
        return start
      }, getText: function () {
        var nativeSel, nativeRange;
        if (this.isFocus() && (nativeSel = this.getNative())) {
          nativeRange = browser.ie9below ? nativeSel.createRange() : nativeSel.getRangeAt(0);
          return browser.ie9below ? nativeRange.text : nativeRange.toString()
        }
        return ""
      }, clearRange: function () {
        this.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]()
      }
    }
  })();
  (function () {
    var uid = 0, _selectionChangeTimer;

    function setValue(form, editor) {
      if (!editor.options.textarea) {
        return
      }
      var textarea;
      textarea = editor.textarea;
      if (!textarea) {
        textarea = domUtils.getElementsByTagName(form, "textarea", function (node) {
          return node.id === "ueditor_textarea_" + editor.options.textarea
        })[0]
      }
      if (!textarea) {
        textarea = domUtils.getElementsByTagName(form, "textarea", function (node) {
          return node.name === editor.options.textarea
        })[0]
      }
      if (!textarea) {
        form.appendChild(textarea = domUtils.createElement(document, "textarea", {name: editor.options.textarea, id: "ueditor_textarea_" + editor.options.textarea, style: "display:none"}))
      }
      if (textarea && !editor.textarea) {
        editor.textarea = textarea
      }
      !textarea.getAttribute("name") && textarea.setAttribute("name", editor.options.textarea);
      textarea.value = editor.hasContents() ? editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true) : ""
    }

    function loadPlugins(me) {
      for (var pi in UE.plugins) {
        UE.plugins[pi].call(me)
      }
    }

    function checkCurLang(I18N) {
      for (var lang in I18N) {
        return lang
      }
    }

    function langReadied(me) {
      me.langIsReady = true;
      me.fireEvent("langReady")
    }

    var Editor = UE.Editor = function (options) {
      var me = this;
      me.uid = uid++;
      EventBase.call(me);
      me.commands = {};
      me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true);
      me.shortcutkeys = {};
      me.inputRules = [];
      me.outputRules = [];
      me.setOpt(Editor.defaultOptions(me));
      me.loadServerConfig();
      if (!utils.isEmptyObject(UE.I18N)) {
        me.options.lang = checkCurLang(UE.I18N);
        UE.plugin.load(me);
        langReadied(me)
      } else {
        utils.loadFile(document, {src: me.options.langPath + me.options.lang + "/" + me.options.lang + ".js?7a537435", tag: "script", type: "text/javascript", defer: "defer"}, function () {
          UE.plugin.load(me);
          langReadied(me)
        })
      }
      UE.instants["ueditorInstant" + me.uid] = me
    };
    Editor.prototype = {
      registerCommand: function (name, obj) {
        this.commands[name] = obj
      }, ready: function (fn) {
        var me = this;
        if (fn) {
          me.isReady ? fn.apply(me) : me.addListener("ready", fn)
        }
      }, setOpt: function (key, val) {
        var obj = {};
        if (utils.isString(key)) {
          obj[key] = val
        } else {
          obj = key
        }
        utils.extend(this.options, obj, true)
      }, getOpt: function (key) {
        return this.options[key]
      }, destroy: function () {
        var me = this;
        me.fireEvent("destroy");
        var container = me.container.parentNode;
        var textarea = me.textarea;
        if (!textarea) {
          textarea = document.createElement("textarea");
          container.parentNode.insertBefore(textarea, container)
        } else {
          textarea.style.display = ""
        }
        textarea.style.width = me.iframe.offsetWidth + "px";
        textarea.style.height = me.iframe.offsetHeight + "px";
        textarea.value = me.getContent();
        textarea.id = me.key;
        container.innerHTML = "";
        domUtils.remove(container);
        var key = me.key;
        for (var p in me) {
          if (me.hasOwnProperty(p)) {
            delete this[p]
          }
        }
        UE.delEditor(key)
      }, render: function (container) {
        var me = this, options = me.options, getStyleValue = function (attr) {
          return parseInt(domUtils.getComputedStyle(container, attr))
        };
        if (utils.isString(container)) {
          container = document.getElementById(container)
        }
        if (container) {
          if (options.initialFrameWidth) {
            options.minFrameWidth = options.initialFrameWidth
          } else {
            options.minFrameWidth = options.initialFrameWidth = container.offsetWidth
          }
          if (options.initialFrameHeight) {
            options.minFrameHeight = options.initialFrameHeight
          } else {
            options.initialFrameHeight = options.minFrameHeight = container.offsetHeight
          }
          container.style.width = /%$/.test(options.initialFrameWidth) ? "100%" : options.initialFrameWidth - getStyleValue("padding-left") - getStyleValue("padding-right") + "px";
          container.style.height = /%$/.test(options.initialFrameHeight) ? "100%" : options.initialFrameHeight - getStyleValue("padding-top") - getStyleValue("padding-bottom") + "px";
          container.style.zIndex = options.zIndex;
          var additionCssHtml = [];
          for (var i in options.iframeCssUrlsAddition) {
            additionCssHtml.push("<link rel='stylesheet' type='text/css' href='" + utils.unhtml(options.iframeCssUrlsAddition[i]) + "'/>")
          }
          var html = (ie && browser.version < 9 ? "" : "<!DOCTYPE html>") + "<html xmlns='http://www.w3.org/1999/xhtml' class='view' >" + "<head>" + "<style type='text/css'>" + ".view{padding:0;word-wrap:break-word;cursor:text;height:90%;}\n" + "body{margin:8px;font-family:sans-serif;font-size:16px;}" + "p{margin:5px 0;}</style>" + (options.iframeCssUrl ? "<link rel='stylesheet' type='text/css' href='" + utils.unhtml(options.iframeCssUrl) + "'/>" : "") + (options.initialStyle ? "<style>" + options.initialStyle + "</style>" : "") + additionCssHtml.join("") + "</head>" + "<body class='view' ></body>" + "<script type='text/javascript' " + (ie ? "defer='defer'" : "") + " id='_initialScript'>" + "setTimeout(function(){editor = window.parent.UE.instants['ueditorInstant" + me.uid + "'];editor._setup(document);},0);" + "var _tmpScript = document.getElementById('_initialScript');_tmpScript.parentNode.removeChild(_tmpScript);" + "<\/script>" + (options.iframeJsUrl ? "<script type='text/javascript' src='" + utils.unhtml(options.iframeJsUrl) + "'><\/script>" : "") + "</html>";
          container.appendChild(domUtils.createElement(document, "iframe", {
            id: "ueditor_" + me.uid,
            width: "100%",
            height: "100%",
            frameborder: "0",
            src: "javascript:void(function(){document.open();" + (options.customDomain && document.domain != location.hostname ? 'document.domain="' + document.domain + '";' : "") + 'document.write("' + html + '");document.close();}())'
          }));
          container.style.overflow = "hidden";
          setTimeout(function () {
            if (/%$/.test(options.initialFrameWidth)) {
              options.minFrameWidth = options.initialFrameWidth = container.offsetWidth
            }
            if (/%$/.test(options.initialFrameHeight)) {
              options.minFrameHeight = options.initialFrameHeight = container.offsetHeight;
              container.style.height = options.initialFrameHeight + "px"
            }
          })
        }
      }, _setup: function (doc) {
        var me = this, options = me.options;
        if (ie) {
          doc.body.disabled = true;
          doc.body.contentEditable = true;
          doc.body.disabled = false
        } else {
          doc.body.contentEditable = true
        }
        doc.body.spellcheck = false;
        me.document = doc;
        me.window = doc.defaultView || doc.parentWindow;
        me.iframe = me.window.frameElement;
        me.body = doc.body;
        me.selection = new dom.Selection(doc);
        var geckoSel;
        if (browser.gecko && (geckoSel = this.selection.getNative())) {
          geckoSel.removeAllRanges()
        }
        this._initEvents();
        for (var form = this.iframe.parentNode; !domUtils.isBody(form); form = form.parentNode) {
          if (form.tagName === "FORM") {
            me.form = form;
            if (me.options.autoSyncData) {
              domUtils.on(me.window, "blur", function () {
                setValue(form, me)
              });
              domUtils.on(form, "submit", function () {
                me.fireEvent("beforesubmit")
              })
            } else {
              domUtils.on(form, "submit", function () {
                setValue(this, me);
                me.fireEvent("beforesubmit")
              })
            }
            break
          }
        }
        if (options.initialContent) {
          if (options.autoClearinitialContent) {
            var oldExecCommand = me.execCommand;
            me.execCommand = function () {
              me.fireEvent("firstBeforeExecCommand");
              return oldExecCommand.apply(me, arguments)
            };
            this._setDefaultContent(options.initialContent)
          } else this.setContent(options.initialContent, false, true)
        }
        if (domUtils.isEmptyNode(me.body)) {
          me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>"
        }
        if (options.focus) {
          setTimeout(function () {
            me.focus(me.options.focusInEnd);
            !me.options.autoClearinitialContent && me._selectionChange()
          }, 0)
        }
        if (!me.container) {
          me.container = this.iframe.parentNode
        }
        if (options.fullscreen && me.ui) {
          me.ui.setFullScreen(true)
        }
        try {
          me.document.execCommand("2D-position", false, false)
        } catch (e) {
        }
        try {
          me.document.execCommand("enableInlineTableEditing", false, false)
        } catch (e) {
        }
        try {
          me.document.execCommand("enableObjectResizing", false, false)
        } catch (e) {
        }
        me._bindshortcutKeys();
        me.isReady = 1;
        me.fireEvent("ready");
        options.onready && options.onready.call(me);
        if (!browser.ie9below) {
          domUtils.on(me.window, ["blur", "focus"], function (e) {
            if (e.type == "blur") {
              me._bakRange = me.selection.getRange();
              try {
                me._bakNativeRange = me.selection.getNative().getRangeAt(0);
                me.selection.getNative().removeAllRanges()
              } catch (e) {
                me._bakNativeRange = null
              }
            } else {
              try {
                me._bakRange && me._bakRange.select()
              } catch (e) {
              }
            }
          })
        }
        if (browser.gecko && browser.version <= 10902) {
          me.body.contentEditable = false;
          setTimeout(function () {
            me.body.contentEditable = true
          }, 100);
          setInterval(function () {
            me.body.style.height = me.iframe.offsetHeight - 20 + "px"
          }, 100)
        }
        !options.isShow && me.setHide();
        options.readonly && me.setDisabled()
      }, sync: function (formId) {
        var me = this, form = formId ? document.getElementById(formId) : domUtils.findParent(me.iframe.parentNode, function (node) {
          return node.tagName === "FORM"
        }, true);
        form && setValue(form, me)
      }, syncCommandState: function () {
        this.fireEvent("selectionchange")
      }, setWidth: function (width) {
        if (width !== parseInt(this.iframe.parentNode.parentNode.style.width)) {
          this.iframe.parentNode.parentNode.style.width = width + "px"
        }
      }, setHeight: function (height, notSetHeight) {
        if (height !== parseInt(this.iframe.parentNode.style.height)) {
          this.iframe.parentNode.style.height = height + "px"
        }
        !notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height);
        this.body.style.height = height + "px";
        !notSetHeight && this.trigger("setHeight")
      }, addshortcutkey: function (cmd, keys) {
        var obj = {};
        if (keys) {
          obj[cmd] = keys
        } else {
          obj = cmd
        }
        utils.extend(this.shortcutkeys, obj)
      }, _bindshortcutKeys: function () {
        var me = this, shortcutkeys = this.shortcutkeys;
        me.addListener("keydown", function (type, e) {
          var keyCode = e.keyCode || e.which;
          for (var i in shortcutkeys) {
            var tmp = shortcutkeys[i].split(",");
            for (var t = 0, ti; ti = tmp[t++];) {
              ti = ti.split(":");
              var key = ti[0], param = ti[1];
              if (/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key)) {
                if ((RegExp.$1 == "ctrl" ? e.ctrlKey || e.metaKey : 0) && (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) && keyCode == RegExp.$3 || keyCode == RegExp.$1) {
                  if (me.queryCommandState(i, param) != -1) me.execCommand(i, param);
                  domUtils.preventDefault(e)
                }
              }
            }
          }
        })
      }, getContent: function (cmd, fn, notSetCursor, ignoreBlank, formatter) {
        var me = this;
        if (cmd && utils.isFunction(cmd)) {
          fn = cmd;
          cmd = ""
        }
        if (fn ? !fn() : !this.hasContents()) {
          return ""
        }
        me.fireEvent("beforegetcontent");
        var root = UE.htmlparser(me.body.innerHTML, ignoreBlank);
        me.filterOutputRule(root);
        me.fireEvent("aftergetcontent", cmd, root);
        return root.toHtml(formatter)
      }, getAllHtml: function () {
        var me = this, headHtml = [], html = "";
        me.fireEvent("getAllHtml", headHtml);
        if (browser.ie && browser.version > 8) {
          var headHtmlForIE9 = "";
          utils.each(me.document.styleSheets, function (si) {
            headHtmlForIE9 += si.href ? '<link rel="stylesheet" type="text/css" href="' + si.href + '" />' : "<style>" + si.cssText + "</style>"
          });
          utils.each(me.document.getElementsByTagName("script"), function (si) {
            headHtmlForIE9 += si.outerHTML
          })
        }
        return "<html><head>" + (me.options.charset ? '<meta http-equiv="Content-Type" content="text/html; charset=' + me.options.charset + '"/>' : "") + (headHtmlForIE9 || me.document.getElementsByTagName("head")[0].innerHTML) + headHtml.join("\n") + "</head>" + "<body " + (ie && browser.version < 9 ? 'class="view"' : "") + ">" + me.getContent(null, null, true) + "</body></html>"
      }, getPlainTxt: function () {
        var reg = new RegExp(domUtils.fillChar, "g"), html = this.body.innerHTML.replace(/[\n\r]/g, "");
        html = html.replace(/<(p|div)[^>]*>(<br\/?>|&nbsp;)<\/\1>/gi, "\n").replace(/<br\/?>/gi, "\n").replace(/<[^>/]+>/g, "").replace(/(\n)?<\/([^>]+)>/g, function (a, b, c) {
          return dtd.$block[c] ? "\n" : b ? b : ""
        });
        return html.replace(reg, "").replace(/\u00a0/g, " ").replace(/&nbsp;/g, " ")
      }, getContentTxt: function () {
        var reg = new RegExp(domUtils.fillChar, "g");
        return this.body[browser.ie ? "innerText" : "textContent"].replace(reg, "").replace(/\u00a0/g, " ")
      }, setContent: function (html, isAppendTo, notFireSelectionchange) {
        var me = this;
        me.fireEvent("beforesetcontent", html);
        var root = UE.htmlparser(html);
        me.filterInputRule(root);
        html = root.toHtml();
        me.body.innerHTML = (isAppendTo ? me.body.innerHTML : "") + html;

        function isCdataDiv(node) {
          return node.tagName == "DIV" && node.getAttribute("cdata_tag")
        }

        if (me.options.enterTag == "p") {
          var child = this.body.firstChild, tmpNode;
          if (!child || child.nodeType == 1 && (dtd.$cdata[child.tagName] || isCdataDiv(child) || domUtils.isCustomeNode(child)) && child === this.body.lastChild) {
            this.body.innerHTML = "<p>" + (browser.ie ? "&nbsp;" : "<br/>") + "</p>" + this.body.innerHTML
          } else {
            var p = me.document.createElement("p");
            while (child) {
              while (child && (child.nodeType == 3 || child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName])) {
                tmpNode = child.nextSibling;
                p.appendChild(child);
                child = tmpNode
              }
              if (p.firstChild) {
                if (!child) {
                  me.body.appendChild(p);
                  break
                } else {
                  child.parentNode.insertBefore(p, child);
                  p = me.document.createElement("p")
                }
              }
              child = child.nextSibling
            }
          }
        }
        me.fireEvent("aftersetcontent");
        me.fireEvent("contentchange");
        !notFireSelectionchange && me._selectionChange();
        me._bakRange = me._bakIERange = me._bakNativeRange = null;
        var geckoSel;
        if (browser.gecko && (geckoSel = this.selection.getNative())) {
          geckoSel.removeAllRanges()
        }
        if (me.options.autoSyncData) {
          me.form && setValue(me.form, me)
        }
      }, focus: function (toEnd) {
        try {
          var me = this, rng = me.selection.getRange();
          if (toEnd) {
            var node = me.body.lastChild;
            if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
              if (domUtils.isEmptyBlock(node)) {
                rng.setStartAtFirst(node)
              } else {
                rng.setStartAtLast(node)
              }
              rng.collapse(true)
            }
            rng.setCursor(true)
          } else {
            if (!rng.collapsed && domUtils.isBody(rng.startContainer) && rng.startOffset == 0) {
              var node = me.body.firstChild;
              if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
                rng.setStartAtFirst(node).collapse(true)
              }
            }
            rng.select(true)
          }
          this.fireEvent("focus selectionchange")
        } catch (e) {
        }
      }, isFocus: function () {
        return this.selection.isFocus()
      }, blur: function () {
        var sel = this.selection.getNative();
        if (sel.empty && browser.ie) {
          var nativeRng = document.body.createTextRange();
          nativeRng.moveToElementText(document.body);
          nativeRng.collapse(true);
          nativeRng.select();
          sel.empty()
        } else {
          sel.removeAllRanges()
        }
      }, _initEvents: function () {
        var me = this, doc = me.document, win = me.window;
        me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);
        domUtils.on(doc, ["click", "contextmenu", "mousedown", "keydown", "keyup", "keypress", "mouseup", "mouseover", "mouseout", "selectstart"], me._proxyDomEvent);
        domUtils.on(win, ["focus", "blur"], me._proxyDomEvent);
        domUtils.on(me.body, "drop", function (e) {
          if (browser.gecko && e.stopPropagation) {
            e.stopPropagation()
          }
          me.fireEvent("contentchange")
        });
        domUtils.on(me.body, "dblclick", function (e) {
          try {
            var node = me.body.lastChild;
            if (!node) {
              return
            }
            var rect = node.getBoundingClientRect();
            if (e.clientY > rect.top + rect.height) {
              var p = document.createElement("p");
              p.innerHTML = "<br />";
              me.body.appendChild(p);
              setTimeout(function () {
                me.focus(true)
              }, 100)
            }
          } catch (e) {
            console.error("auto insert p at end", e)
          }
        });
        domUtils.on(doc, ["mouseup", "keydown"], function (evt) {
          if (evt.type === "keydown" && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {
            return
          }
          if (evt.button === 2) return;
          me._selectionChange(250, evt)
        })
      }, _proxyDomEvent: function (evt) {
        if (this.fireEvent("before" + evt.type.replace(/^on/, "").toLowerCase()) === false) {
          return false
        }
        if (this.fireEvent(evt.type.replace(/^on/, ""), evt) === false) {
          return false
        }
        return this.fireEvent("after" + evt.type.replace(/^on/, "").toLowerCase())
      }, _selectionChange: function (delay, evt) {
        var me = this;
        var hackForMouseUp = false;
        var mouseX, mouseY;
        if (browser.ie && browser.version < 9 && evt && evt.type == "mouseup") {
          var range = this.selection.getRange();
          if (!range.collapsed) {
            hackForMouseUp = true;
            mouseX = evt.clientX;
            mouseY = evt.clientY
          }
        }
        clearTimeout(_selectionChangeTimer);
        _selectionChangeTimer = setTimeout(function () {
          if (!me.selection || !me.selection.getNative()) {
            return
          }
          var ieRange;
          if (hackForMouseUp && me.selection.getNative().type == "None") {
            ieRange = me.document.body.createTextRange();
            try {
              ieRange.moveToPoint(mouseX, mouseY)
            } catch (ex) {
              ieRange = null
            }
          }
          var bakGetIERange;
          if (ieRange) {
            bakGetIERange = me.selection.getIERange;
            me.selection.getIERange = function () {
              return ieRange
            }
          }
          me.selection.cache();
          if (bakGetIERange) {
            me.selection.getIERange = bakGetIERange
          }
          if (me.selection._cachedRange && me.selection._cachedStartElement) {
            me.fireEvent("beforeselectionchange");
            me.fireEvent("selectionchange", !!evt);
            me.fireEvent("afterselectionchange");
            me.selection.clear()
          }
        }, delay || 50)
      }, _callCmdFn: function (fnName, args) {
        var cmdName = args[0].toLowerCase(), cmd, cmdFn;
        cmd = this.commands[cmdName] || UE.commands[cmdName];
        cmdFn = cmd && cmd[fnName];
        if ((!cmd || !cmdFn) && fnName == "queryCommandState") {
          return 0
        } else if (cmdFn) {
          return cmdFn.apply(this, args)
        }
      }, execCommand: function (cmdName) {
        cmdName = cmdName.toLowerCase();
        var me = this, result, cmd = me.commands[cmdName] || UE.commands[cmdName];
        if (!cmd || !cmd.execCommand) {
          return null
        }
        if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) {
          me.__hasEnterExecCommand = true;
          if (me.queryCommandState.apply(me, arguments) != -1) {
            me.fireEvent("saveScene");
            me.fireEvent.apply(me, ["beforeexeccommand", cmdName].concat(arguments));
            result = this._callCmdFn("execCommand", arguments);
            me.fireEvent.apply(me, ["afterexeccommand", cmdName].concat(arguments));
            me.fireEvent("saveScene")
          }
          me.__hasEnterExecCommand = false
        } else {
          result = this._callCmdFn("execCommand", arguments);
          !me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange && me.fireEvent("contentchange")
        }
        !me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange && me._selectionChange();
        return result
      }, queryCommandState: function (cmdName) {
        return this._callCmdFn("queryCommandState", arguments)
      }, queryCommandValue: function (cmdName) {
        return this._callCmdFn("queryCommandValue", arguments)
      }, hasContents: function (tags) {
        if (tags) {
          for (var i = 0, ci; ci = tags[i++];) {
            if (this.document.getElementsByTagName(ci).length > 0) {
              return true
            }
          }
        }
        if (!domUtils.isEmptyBlock(this.body)) {
          return true
        }
        tags = ["div"];
        for (i = 0; ci = tags[i++];) {
          var nodes = domUtils.getElementsByTagName(this.document, ci);
          for (var n = 0, cn; cn = nodes[n++];) {
            if (domUtils.isCustomeNode(cn)) {
              return true
            }
          }
        }
        tags = ["video", "iframe"];
        for (i = 0; ci = tags[i++];) {
          var nodes = domUtils.getElementsByTagName(this.document, ci);
          for (var n = 0, cn; cn = nodes[n++];) {
            return true
          }
        }
        return false
      }, reset: function () {
        this.clear();
        this.fireEvent("reset")
      }, clear: function () {
        this.setContent("")
      }, setEnabled: function () {
        var me = this, range;
        if (me.body.contentEditable === "false") {
          me.body.contentEditable = true;
          range = me.selection.getRange();
          try {
            range.moveToBookmark(me.lastBk);
            delete me.lastBk
          } catch (e) {
            range.setStartAtFirst(me.body).collapse(true)
          }
          range.select(true);
          if (me.bkqueryCommandState) {
            me.queryCommandState = me.bkqueryCommandState;
            delete me.bkqueryCommandState
          }
          if (me.bkqueryCommandValue) {
            me.queryCommandValue = me.bkqueryCommandValue;
            delete me.bkqueryCommandValue
          }
          me.fireEvent("selectionchange")
        }
      }, enable: function () {
        return this.setEnabled()
      }, setDisabled: function (except) {
        var me = this;
        except = except ? utils.isArray(except) ? except : [except] : [];
        if (me.body.contentEditable == "true") {
          if (!me.lastBk) {
            me.lastBk = me.selection.getRange().createBookmark(true)
          }
          me.body.contentEditable = false;
          me.bkqueryCommandState = me.queryCommandState;
          me.bkqueryCommandValue = me.queryCommandValue;
          me.queryCommandState = function (type) {
            if (utils.indexOf(except, type) != -1) {
              return me.bkqueryCommandState.apply(me, arguments)
            }
            return -1
          };
          me.queryCommandValue = function (type) {
            if (utils.indexOf(except, type) != -1) {
              return me.bkqueryCommandValue.apply(me, arguments)
            }
            return null
          };
          me.fireEvent("selectionchange")
        }
      }, disable: function (except) {
        return this.setDisabled(except)
      }, _setDefaultContent: function () {
        function clear() {
          var me = this;
          if (me.document.getElementById("initContent")) {
            me.body.innerHTML = "<p>" + (ie ? "" : "<br/>") + "</p>";
            me.removeListener("firstBeforeExecCommand focus", clear);
            setTimeout(function () {
              me.focus();
              me._selectionChange()
            }, 0)
          }
        }

        return function (cont) {
          var me = this;
          me.body.innerHTML = '<p id="initContent">' + cont + "</p>";
          me.addListener("firstBeforeExecCommand focus", clear)
        }
      }(), setShow: function () {
        var me = this, range = me.selection.getRange();
        if (me.container.style.display == "none") {
          try {
            range.moveToBookmark(me.lastBk);
            delete me.lastBk
          } catch (e) {
            range.setStartAtFirst(me.body).collapse(true)
          }
          setTimeout(function () {
            range.select(true)
          }, 100);
          me.container.style.display = ""
        }
      }, show: function () {
        return this.setShow()
      }, setHide: function () {
        var me = this;
        if (!me.lastBk) {
          me.lastBk = me.selection.getRange().createBookmark(true)
        }
        me.container.style.display = "none"
      }, hide: function () {
        return this.setHide()
      }, getLang: function (path) {
        var lang = UE.I18N[this.options.lang];
        if (!lang) {
          throw Error("not import language file")
        }
        path = (path || "").split(".");
        for (var i = 0, ci; ci = path[i++];) {
          lang = lang[ci];
          if (!lang) break
        }
        return lang
      }, getContentLength: function (ingoneHtml, tagNames) {
        var count = this.getContent(false, false, true).length;
        if (ingoneHtml) {
          tagNames = (tagNames || []).concat(["hr", "img", "iframe"]);
          count = this.getContentTxt().replace(/[\t\r\n]+/g, "").length;
          for (var i = 0, ci; ci = tagNames[i++];) {
            count += this.document.getElementsByTagName(ci).length
          }
        }
        return count
      }, getScrollTop: function () {
        return Math.max(this.document.documentElement.scrollTop, this.document.body.scrollTop)
      }, getScrollLeft: function () {
        return Math.max(this.document.documentElement.scrollLeft, this.document.body.scrollLeft)
      }, addInputRule: function (rule) {
        this.inputRules.push(rule)
      }, filterInputRule: function (root) {
        for (var i = 0, ci; ci = this.inputRules[i++];) {
          ci.call(this, root)
        }
      }, addOutputRule: function (rule) {
        this.outputRules.push(rule)
      }, filterOutputRule: function (root) {
        for (var i = 0, ci; ci = this.outputRules[i++];) {
          ci.call(this, root)
        }
      }, getActionUrl: function (action) {
        var serverUrl = this.getOpt("serverUrl");
        if (!action) {
          return serverUrl
        }
        var actionName = this.getOpt(action) || action, imageUrl = this.getOpt("imageUrl");
        if (!serverUrl && imageUrl) {
          serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2")
        }
        if (serverUrl) {
          serverUrl = serverUrl + (serverUrl.indexOf("?") === -1 ? "?" : "&") + "action=" + (actionName || "");
          return utils.formatUrl(serverUrl)
        } else {
          return ""
        }
      }
    };
    utils.inherits(Editor, EventBase)
  })();
  UE.Editor.defaultOptions = function (editor) {
    var _url = editor.options.UEDITOR_HOME_URL;
    return {
      isShow: true,
      initialContent: "",
      initialStyle: "",
      autoClearinitialContent: false,
      iframeCssUrl: _url + "themes/iframe.css?c20ec247",
      iframeCssUrlsAddition: [],
      textarea: "",
      focus: false,
      focusInEnd: true,
      autoClearEmptyNode: true,
      fullscreen: false,
      readonly: false,
      zIndex: 999,
      imagePopup: true,
      enterTag: "p",
      customDomain: false,
      lang: "zh-cn",
      langPath: _url + "lang/",
      theme: "default",
      themePath: _url + "themes/",
      allHtmlEnabled: false,
      scaleEnabled: false,
      tableNativeEditInFF: false,
      autoSyncData: true,
      fileNameFormat: "{time}{rand:6}"
    }
  };
  (function () {
    UE.Editor.prototype.loadServerConfig = function () {
      var me = this;
      setTimeout(function () {
        if (me.options.loadConfigFromServer === false) {
          return
        }
        try {
          me.options.imageUrl && me.setOpt("serverUrl", me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2"));
          var configUrl = me.getActionUrl("config"), isJsonp = utils.isCrossDomainUrl(configUrl);
          me._serverConfigLoaded = false;
          configUrl && UE.ajax.request(configUrl, {
            method: "GET", dataType: isJsonp ? "jsonp" : "", headers: me.options.serverHeaders || {}, onsuccess: function (r) {
              try {
                var config = isJsonp ? r : eval("(" + r.responseText + ")");
                config = me.options.serverResponsePrepare(config);
                me.options = utils.merge(me.options, config);
                me.fireEvent("serverConfigLoaded");
                me._serverConfigLoaded = true
              } catch (e) {
                showErrorMsg(me.getLang("loadconfigFormatError"))
              }
            }, onerror: function () {
              showErrorMsg(me.getLang("loadconfigHttpError"))
            }
          })
        } catch (e) {
          showErrorMsg(me.getLang("loadconfigError"))
        }
      });

      function showErrorMsg(msg) {
        console && console.error(msg)
      }
    };
    UE.Editor.prototype.isServerConfigLoaded = function () {
      var me = this;
      return me._serverConfigLoaded || false
    };
    UE.Editor.prototype.afterConfigReady = function (handler) {
      if (!handler || !utils.isFunction(handler)) return;
      var me = this;
      var readyHandler = function () {
        handler.apply(me, arguments);
        me.removeListener("serverConfigLoaded", readyHandler)
      };
      if (me.isServerConfigLoaded()) {
        handler.call(me, "serverConfigLoaded")
      } else {
        me.addListener("serverConfigLoaded", readyHandler)
      }
    }
  })();
  UE.ajax = function () {
    var fnStr = "XMLHttpRequest()";
    try {
      new ActiveXObject("Msxml2.XMLHTTP");
      fnStr = "ActiveXObject('Msxml2.XMLHTTP')"
    } catch (e) {
      try {
        new ActiveXObject("Microsoft.XMLHTTP");
        fnStr = "ActiveXObject('Microsoft.XMLHTTP')"
      } catch (e) {
      }
    }
    var creatAjaxRequest = new Function("return new " + fnStr);

    function json2str(json) {
      var strArr = [];
      for (var i in json) {
        if (i == "method" || i == "timeout" || i == "async" || i == "dataType" || i == "callback") continue;
        if (json[i] == undefined || json[i] == null) continue;
        if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) {
          strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i]))
        } else if (utils.isArray(json[i])) {
          for (var j = 0; j < json[i].length; j++) {
            strArr.push(encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]))
          }
        }
      }
      return strArr.join("&")
    }

    function doAjax(url, ajaxOptions) {
      var xhr = creatAjaxRequest(), timeIsOut = false, defaultAjaxOptions = {
        method: "POST", timeout: 5e3, async: true, headers: {}, data: {}, onsuccess: function () {
        }, onerror: function () {
        }
      };
      if (typeof url === "object") {
        ajaxOptions = url;
        url = ajaxOptions.url
      }
      if (!xhr || !url) return;
      var ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions, ajaxOptions) : defaultAjaxOptions;
      var submitStr = json2str(ajaxOpts);
      if (!utils.isEmptyObject(ajaxOpts.data)) {
        submitStr += (submitStr ? "&" : "") + json2str(ajaxOpts.data)
      }
      var timerID = setTimeout(function () {
        if (xhr.readyState !== 4) {
          timeIsOut = true;
          xhr.abort();
          clearTimeout(timerID)
        }
      }, ajaxOpts.timeout);
      var method = ajaxOpts.method.toUpperCase();
      var str = url + (url.indexOf("?") === -1 ? "?" : "&") + (method === "POST" ? "" : submitStr + "&noCache=" + +new Date);
      xhr.open(method, str, ajaxOpts.async);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (!timeIsOut && xhr.status === 200) {
            ajaxOpts.onsuccess(xhr)
          } else {
            ajaxOpts.onerror(xhr)
          }
        }
      };
      if (ajaxOpts.headers) {
        for (var key in ajaxOpts.headers) {
          xhr.setRequestHeader(key, ajaxOpts.headers[key])
        }
      }
      if (method === "POST") {
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr.send(submitStr)
      } else {
        xhr.send(null)
      }
    }

    function doJsonp(url, opts) {
      var successhandler = opts.onsuccess || function () {
        }, scr = document.createElement("SCRIPT"), options = opts || {}, charset = options["charset"], callbackField = options["jsonp"] || "callback", callbackFnName, timeOut = options["timeOut"] || 0, timer,
        reg = new RegExp("(\\?|&)" + callbackField + "=([^&]*)"), matches;
      if (utils.isFunction(successhandler)) {
        callbackFnName = "bd__editor__" + Math.floor(Math.random() * 2147483648).toString(36);
        window[callbackFnName] = getCallBack(0)
      } else if (utils.isString(successhandler)) {
        callbackFnName = successhandler
      } else {
        if (matches = reg.exec(url)) {
          callbackFnName = matches[2]
        }
      }
      url = url.replace(reg, "$1" + callbackField + "=" + callbackFnName);
      if (url.search(reg) < 0) {
        url += (url.indexOf("?") < 0 ? "?" : "&") + callbackField + "=" + callbackFnName
      }
      var queryStr = json2str(opts);
      if (!utils.isEmptyObject(opts.data)) {
        queryStr += (queryStr ? "&" : "") + json2str(opts.data)
      }
      if (queryStr) {
        url = url.replace(/\?/, "?" + queryStr + "&")
      }
      scr.onerror = getCallBack(1);
      if (timeOut) {
        timer = setTimeout(getCallBack(1), timeOut)
      }
      createScriptTag(scr, url, charset);

      function createScriptTag(scr, url, charset) {
        scr.setAttribute("type", "text/javascript");
        scr.setAttribute("defer", "defer");
        charset && scr.setAttribute("charset", charset);
        scr.setAttribute("src", url);
        document.getElementsByTagName("head")[0].appendChild(scr)
      }

      function getCallBack(onTimeOut) {
        return function () {
          try {
            if (onTimeOut) {
              options.onerror && options.onerror()
            } else {
              try {
                clearTimeout(timer);
                successhandler.apply(window, arguments)
              } catch (e) {
              }
            }
          } catch (exception) {
            options.onerror && options.onerror.call(window, exception)
          } finally {
            options.oncomplete && options.oncomplete.apply(window, arguments);
            scr.parentNode && scr.parentNode.removeChild(scr);
            window[callbackFnName] = null;
            try {
              delete window[callbackFnName]
            } catch (e) {
            }
          }
        }
      }
    }

    return {
      request: function (url, opts) {
        if (opts && opts.dataType === "jsonp") {
          doJsonp(url, opts)
        } else {
          doAjax(url, opts)
        }
      }, getJSONP: function (url, data, fn) {
        var opts = {data: data, oncomplete: fn};
        doJsonp(url, opts)
      }
    }
  }();
  UE.api = function () {
    var axios = null;
    !function (e, t) {
      axios = t()
    }(this, function () {
      "use strict";

      function e(t) {
        return e = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) {
          return typeof e
        } : function (e) {
          return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
        }, e(t)
      }

      function t(e, t) {
        if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function")
      }

      function n(e, t) {
        for (var n = 0; n < t.length; n++) {
          var r = t[n];
          r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r)
        }
      }

      function r(e, t, r) {
        return t && n(e.prototype, t), r && n(e, r), Object.defineProperty(e, "prototype", {writable: !1}), e
      }

      function o(e, t) {
        return function (e) {
          if (Array.isArray(e)) return e
        }(e) || function (e, t) {
          var n = null == e ? null : "undefined" != typeof Symbol && e[Symbol.iterator] || e["@@iterator"];
          if (null == n) return;
          var r, o, i = [], a = !0, s = !1;
          try {
            for (n = n.call(e); !(a = (r = n.next()).done) && (i.push(r.value), !t || i.length !== t); a = !0) ;
          } catch (e) {
            s = !0, o = e
          } finally {
            try {
              a || null == n.return || n.return()
            } finally {
              if (s) throw o
            }
          }
          return i
        }(e, t) || function (e, t) {
          if (!e) return;
          if ("string" == typeof e) return i(e, t);
          var n = Object.prototype.toString.call(e).slice(8, -1);
          "Object" === n && e.constructor && (n = e.constructor.name);
          if ("Map" === n || "Set" === n) return Array.from(e);
          if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return i(e, t)
        }(e, t) || function () {
          throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")
        }()
      }

      function i(e, t) {
        (null == t || t > e.length) && (t = e.length);
        for (var n = 0, r = new Array(t); n < t; n++) r[n] = e[n];
        return r
      }

      function a(e, t) {
        return function () {
          return e.apply(t, arguments)
        }
      }

      var s, u = Object.prototype.toString, c = Object.getPrototypeOf, f = (s = Object.create(null), function (e) {
        var t = u.call(e);
        return s[t] || (s[t] = t.slice(8, -1).toLowerCase())
      }), l = function (e) {
        return e = e.toLowerCase(), function (t) {
          return f(t) === e
        }
      }, d = function (t) {
        return function (n) {
          return e(n) === t
        }
      }, p = Array.isArray, h = d("undefined");
      var m = l("ArrayBuffer");
      var y = d("string"), v = d("function"), b = d("number"), g = function (t) {
        return null !== t && "object" === e(t)
      }, w = function (e) {
        if ("object" !== f(e)) return !1;
        var t = c(e);
        return !(null !== t && t !== Object.prototype && null !== Object.getPrototypeOf(t) || Symbol.toStringTag in e || Symbol.iterator in e)
      }, E = l("Date"), O = l("File"), S = l("Blob"), R = l("FileList"), A = l("URLSearchParams");

      function T(t, n) {
        var r, o, i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, a = i.allOwnKeys, s = void 0 !== a && a;
        if (null != t) if ("object" !== e(t) && (t = [t]), p(t)) for (r = 0, o = t.length; r < o; r++) n.call(null, t[r], r, t); else {
          var u, c = s ? Object.getOwnPropertyNames(t) : Object.keys(t), f = c.length;
          for (r = 0; r < f; r++) u = c[r], n.call(null, t[u], u, t)
        }
      }

      function j(e, t) {
        t = t.toLowerCase();
        for (var n, r = Object.keys(e), o = r.length; o-- > 0;) if (t === (n = r[o]).toLowerCase()) return n;
        return null
      }

      var N = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : "undefined" != typeof window ? window : global, C = function (e) {
        return !h(e) && e !== N
      };
      var x, P = (x = "undefined" != typeof Uint8Array && c(Uint8Array), function (e) {
        return x && e instanceof x
      }), k = l("HTMLFormElement"), U = function (e) {
        var t = Object.prototype.hasOwnProperty;
        return function (e, n) {
          return t.call(e, n)
        }
      }(), _ = l("RegExp"), F = function (e, t) {
        var n = Object.getOwnPropertyDescriptors(e), r = {};
        T(n, function (n, o) {
          !1 !== t(n, o, e) && (r[o] = n)
        }), Object.defineProperties(e, r)
      }, B = "abcdefghijklmnopqrstuvwxyz", L = "0123456789", D = {DIGIT: L, ALPHA: B, ALPHA_DIGIT: B + B.toUpperCase() + L};
      var I = l("AsyncFunction"), q = {
        isArray: p, isArrayBuffer: m, isBuffer: function (e) {
          return null !== e && !h(e) && null !== e.constructor && !h(e.constructor) && v(e.constructor.isBuffer) && e.constructor.isBuffer(e)
        }, isFormData: function (e) {
          var t;
          return e && ("function" == typeof FormData && e instanceof FormData || v(e.append) && ("formdata" === (t = f(e)) || "object" === t && v(e.toString) && "[object FormData]" === e.toString()))
        }, isArrayBufferView: function (e) {
          return "undefined" != typeof ArrayBuffer && ArrayBuffer.isView ? ArrayBuffer.isView(e) : e && e.buffer && m(e.buffer)
        }, isString: y, isNumber: b, isBoolean: function (e) {
          return !0 === e || !1 === e
        }, isObject: g, isPlainObject: w, isUndefined: h, isDate: E, isFile: O, isBlob: S, isRegExp: _, isFunction: v, isStream: function (e) {
          return g(e) && v(e.pipe)
        }, isURLSearchParams: A, isTypedArray: P, isFileList: R, forEach: T, merge: function e() {
          for (var t = C(this) && this || {}, n = t.caseless, r = {}, o = function (t, o) {
            var i = n && j(r, o) || o;
            w(r[i]) && w(t) ? r[i] = e(r[i], t) : w(t) ? r[i] = e({}, t) : p(t) ? r[i] = t.slice() : r[i] = t
          }, i = 0, a = arguments.length; i < a; i++) arguments[i] && T(arguments[i], o);
          return r
        }, extend: function (e, t, n) {
          var r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {}, o = r.allOwnKeys;
          return T(t, function (t, r) {
            n && v(t) ? e[r] = a(t, n) : e[r] = t
          }, {allOwnKeys: o}), e
        }, trim: function (e) {
          return e.trim ? e.trim() : e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "")
        }, stripBOM: function (e) {
          return 65279 === e.charCodeAt(0) && (e = e.slice(1)), e
        }, inherits: function (e, t, n, r) {
          e.prototype = Object.create(t.prototype, r), e.prototype.constructor = e, Object.defineProperty(e, "super", {value: t.prototype}), n && Object.assign(e.prototype, n)
        }, toFlatObject: function (e, t, n, r) {
          var o, i, a, s = {};
          if (t = t || {}, null == e) return t;
          do {
            for (i = (o = Object.getOwnPropertyNames(e)).length; i-- > 0;) a = o[i], r && !r(a, e, t) || s[a] || (t[a] = e[a], s[a] = !0);
            e = !1 !== n && c(e)
          } while (e && (!n || n(e, t)) && e !== Object.prototype);
          return t
        }, kindOf: f, kindOfTest: l, endsWith: function (e, t, n) {
          e = String(e), (void 0 === n || n > e.length) && (n = e.length), n -= t.length;
          var r = e.indexOf(t, n);
          return -1 !== r && r === n
        }, toArray: function (e) {
          if (!e) return null;
          if (p(e)) return e;
          var t = e.length;
          if (!b(t)) return null;
          for (var n = new Array(t); t-- > 0;) n[t] = e[t];
          return n
        }, forEachEntry: function (e, t) {
          for (var n, r = (e && e[Symbol.iterator]).call(e); (n = r.next()) && !n.done;) {
            var o = n.value;
            t.call(e, o[0], o[1])
          }
        }, matchAll: function (e, t) {
          for (var n, r = []; null !== (n = e.exec(t));) r.push(n);
          return r
        }, isHTMLForm: k, hasOwnProperty: U, hasOwnProp: U, reduceDescriptors: F, freezeMethods: function (e) {
          F(e, function (t, n) {
            if (v(e) && -1 !== ["arguments", "caller", "callee"].indexOf(n)) return !1;
            var r = e[n];
            v(r) && (t.enumerable = !1, "writable" in t ? t.writable = !1 : t.set || (t.set = function () {
              throw Error("Can not rewrite read-only method '" + n + "'")
            }))
          })
        }, toObjectSet: function (e, t) {
          var n = {}, r = function (e) {
            e.forEach(function (e) {
              n[e] = !0
            })
          };
          return p(e) ? r(e) : r(String(e).split(t)), n
        }, toCamelCase: function (e) {
          return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function (e, t, n) {
            return t.toUpperCase() + n
          })
        }, noop: function () {
        }, toFiniteNumber: function (e, t) {
          return e = +e, Number.isFinite(e) ? e : t
        }, findKey: j, global: N, isContextDefined: C, ALPHABET: D, generateString: function () {
          for (var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 16, t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : D.ALPHA_DIGIT, n = "", r = t.length; e--;) n += t[Math.random() * r | 0];
          return n
        }, isSpecCompliantForm: function (e) {
          return !!(e && v(e.append) && "FormData" === e[Symbol.toStringTag] && e[Symbol.iterator])
        }, toJSONObject: function (e) {
          var t = new Array(10);
          return function e(n, r) {
            if (g(n)) {
              if (t.indexOf(n) >= 0) return;
              if (!("toJSON" in n)) {
                t[r] = n;
                var o = p(n) ? [] : {};
                return T(n, function (t, n) {
                  var i = e(t, r + 1);
                  !h(i) && (o[n] = i)
                }), t[r] = void 0, o
              }
            }
            return n
          }(e, 0)
        }, isAsyncFn: I, isThenable: function (e) {
          return e && (g(e) || v(e)) && v(e.then) && v(e.catch)
        }
      };

      function M(e, t, n, r, o) {
        Error.call(this), Error.captureStackTrace ? Error.captureStackTrace(this, this.constructor) : this.stack = (new Error).stack, this.message = e, this.name = "AxiosError", t && (this.code = t), n && (this.config = n), r && (this.request = r), o && (this.response = o)
      }

      q.inherits(M, Error, {
        toJSON: function () {
          return {
            message: this.message,
            name: this.name,
            description: this.description,
            number: this.number,
            fileName: this.fileName,
            lineNumber: this.lineNumber,
            columnNumber: this.columnNumber,
            stack: this.stack,
            config: q.toJSONObject(this.config),
            code: this.code,
            status: this.response && this.response.status ? this.response.status : null
          }
        }
      });
      var z = M.prototype, H = {};
      ["ERR_BAD_OPTION_VALUE", "ERR_BAD_OPTION", "ECONNABORTED", "ETIMEDOUT", "ERR_NETWORK", "ERR_FR_TOO_MANY_REDIRECTS", "ERR_DEPRECATED", "ERR_BAD_RESPONSE", "ERR_BAD_REQUEST", "ERR_CANCELED", "ERR_NOT_SUPPORT", "ERR_INVALID_URL"].forEach(function (e) {
        H[e] = {value: e}
      }), Object.defineProperties(M, H), Object.defineProperty(z, "isAxiosError", {value: !0}), M.from = function (e, t, n, r, o, i) {
        var a = Object.create(z);
        return q.toFlatObject(e, a, function (e) {
          return e !== Error.prototype
        }, function (e) {
          return "isAxiosError" !== e
        }), M.call(a, e.message, t, n, r, o), a.cause = e, a.name = e.name, i && Object.assign(a, i), a
      };

      function J(e) {
        return q.isPlainObject(e) || q.isArray(e)
      }

      function W(e) {
        return q.endsWith(e, "[]") ? e.slice(0, -2) : e
      }

      function K(e, t, n) {
        return e ? e.concat(t).map(function (e, t) {
          return e = W(e), !n && t ? "[" + e + "]" : e
        }).join(n ? "." : "") : t
      }

      var V = q.toFlatObject(q, {}, null, function (e) {
        return /^is[A-Z]/.test(e)
      });

      function G(t, n, r) {
        if (!q.isObject(t)) throw new TypeError("target must be an object");
        n = n || new FormData;
        var o = (r = q.toFlatObject(r, {metaTokens: !0, dots: !1, indexes: !1}, !1, function (e, t) {
          return !q.isUndefined(t[e])
        })).metaTokens, i = r.visitor || f, a = r.dots, s = r.indexes, u = (r.Blob || "undefined" != typeof Blob && Blob) && q.isSpecCompliantForm(n);
        if (!q.isFunction(i)) throw new TypeError("visitor must be a function");

        function c(e) {
          if (null === e) return "";
          if (q.isDate(e)) return e.toISOString();
          if (!u && q.isBlob(e)) throw new M("Blob is not supported. Use a Buffer instead.");
          return q.isArrayBuffer(e) || q.isTypedArray(e) ? u && "function" == typeof Blob ? new Blob([e]) : Buffer.from(e) : e
        }

        function f(t, r, i) {
          var u = t;
          if (t && !i && "object" === e(t)) if (q.endsWith(r, "{}")) r = o ? r : r.slice(0, -2), t = JSON.stringify(t); else if (q.isArray(t) && function (e) {
            return q.isArray(e) && !e.some(J)
          }(t) || (q.isFileList(t) || q.endsWith(r, "[]")) && (u = q.toArray(t))) return r = W(r), u.forEach(function (e, t) {
            !q.isUndefined(e) && null !== e && n.append(!0 === s ? K([r], t, a) : null === s ? r : r + "[]", c(e))
          }), !1;
          return !!J(t) || (n.append(K(i, r, a), c(t)), !1)
        }

        var l = [], d = Object.assign(V, {defaultVisitor: f, convertValue: c, isVisitable: J});
        if (!q.isObject(t)) throw new TypeError("data must be an object");
        return function e(t, r) {
          if (!q.isUndefined(t)) {
            if (-1 !== l.indexOf(t)) throw Error("Circular reference detected in " + r.join("."));
            l.push(t), q.forEach(t, function (t, o) {
              !0 === (!(q.isUndefined(t) || null === t) && i.call(n, t, q.isString(o) ? o.trim() : o, r, d)) && e(t, r ? r.concat(o) : [o])
            }), l.pop()
          }
        }(t), n
      }

      function $(e) {
        var t = {"!": "%21", "'": "%27", "(": "%28", ")": "%29", "~": "%7E", "%20": "+", "%00": "\0"};
        return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g, function (e) {
          return t[e]
        })
      }

      function X(e, t) {
        this._pairs = [], e && G(e, this, t)
      }

      var Q = X.prototype;

      function Z(e) {
        return encodeURIComponent(e).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+").replace(/%5B/gi, "[").replace(/%5D/gi, "]")
      }

      function Y(e, t, n) {
        if (!t) return e;
        var r, o = n && n.encode || Z, i = n && n.serialize;
        if (r = i ? i(t, n) : q.isURLSearchParams(t) ? t.toString() : new X(t, n).toString(o)) {
          var a = e.indexOf("#");
          -1 !== a && (e = e.slice(0, a)), e += (-1 === e.indexOf("?") ? "?" : "&") + r
        }
        return e
      }

      Q.append = function (e, t) {
        this._pairs.push([e, t])
      }, Q.toString = function (e) {
        var t = e ? function (t) {
          return e.call(this, t, $)
        } : $;
        return this._pairs.map(function (e) {
          return t(e[0]) + "=" + t(e[1])
        }, "").join("&")
      };
      var ee, te = function () {
        function e() {
          t(this, e), this.handlers = []
        }

        return r(e, [{
          key: "use", value: function (e, t, n) {
            return this.handlers.push({fulfilled: e, rejected: t, synchronous: !!n && n.synchronous, runWhen: n ? n.runWhen : null}), this.handlers.length - 1
          }
        }, {
          key: "eject", value: function (e) {
            this.handlers[e] && (this.handlers[e] = null)
          }
        }, {
          key: "clear", value: function () {
            this.handlers && (this.handlers = [])
          }
        }, {
          key: "forEach", value: function (e) {
            q.forEach(this.handlers, function (t) {
              null !== t && e(t)
            })
          }
        }]), e
      }(), ne = {silentJSONParsing: !0, forcedJSONParsing: !0, clarifyTimeoutError: !1}, re = {
        isBrowser: !0,
        classes: {URLSearchParams: "undefined" != typeof URLSearchParams ? URLSearchParams : X, FormData: "undefined" != typeof FormData ? FormData : null, Blob: "undefined" != typeof Blob ? Blob : null},
        isStandardBrowserEnv: ("undefined" == typeof navigator || "ReactNative" !== (ee = navigator.product) && "NativeScript" !== ee && "NS" !== ee) && "undefined" != typeof window && "undefined" != typeof document,
        isStandardBrowserWebWorkerEnv: "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope && "function" == typeof self.importScripts,
        protocols: ["http", "https", "file", "blob", "url", "data"]
      };

      function oe(e) {
        function t(e, n, r, o) {
          var i = e[o++], a = Number.isFinite(+i), s = o >= e.length;
          return i = !i && q.isArray(r) ? r.length : i, s ? (q.hasOwnProp(r, i) ? r[i] = [r[i], n] : r[i] = n, !a) : (r[i] && q.isObject(r[i]) || (r[i] = []), t(e, n, r[i], o) && q.isArray(r[i]) && (r[i] = function (e) {
            var t, n, r = {}, o = Object.keys(e), i = o.length;
            for (t = 0; t < i; t++) r[n = o[t]] = e[n];
            return r
          }(r[i])), !a)
        }

        if (q.isFormData(e) && q.isFunction(e.entries)) {
          var n = {};
          return q.forEachEntry(e, function (e, r) {
            t(function (e) {
              return q.matchAll(/\w+|\[(\w*)]/g, e).map(function (e) {
                return "[]" === e[0] ? "" : e[1] || e[0]
              })
            }(e), r, n, 0)
          }), n
        }
        return null
      }

      var ie = {"Content-Type": void 0};
      var ae = {
        transitional: ne, adapter: ["xhr", "http"], transformRequest: [function (e, t) {
          var n, r = t.getContentType() || "", o = r.indexOf("application/json") > -1, i = q.isObject(e);
          if (i && q.isHTMLForm(e) && (e = new FormData(e)), q.isFormData(e)) return o && o ? JSON.stringify(oe(e)) : e;
          if (q.isArrayBuffer(e) || q.isBuffer(e) || q.isStream(e) || q.isFile(e) || q.isBlob(e)) return e;
          if (q.isArrayBufferView(e)) return e.buffer;
          if (q.isURLSearchParams(e)) return t.setContentType("application/x-www-form-urlencoded;charset=utf-8", !1), e.toString();
          if (i) {
            if (r.indexOf("application/x-www-form-urlencoded") > -1) return function (e, t) {
              return G(e, new re.classes.URLSearchParams, Object.assign({
                visitor: function (e, t, n, r) {
                  return re.isNode && q.isBuffer(e) ? (this.append(t, e.toString("base64")), !1) : r.defaultVisitor.apply(this, arguments)
                }
              }, t))
            }(e, this.formSerializer).toString();
            if ((n = q.isFileList(e)) || r.indexOf("multipart/form-data") > -1) {
              var a = this.env && this.env.FormData;
              return G(n ? {"files[]": e} : e, a && new a, this.formSerializer)
            }
          }
          return i || o ? (t.setContentType("application/json", !1), function (e, t, n) {
            if (q.isString(e)) try {
              return (t || JSON.parse)(e), q.trim(e)
            } catch (e) {
              if ("SyntaxError" !== e.name) throw e
            }
            return (n || JSON.stringify)(e)
          }(e)) : e
        }], transformResponse: [function (e) {
          var t = this.transitional || ae.transitional, n = t && t.forcedJSONParsing, r = "json" === this.responseType;
          if (e && q.isString(e) && (n && !this.responseType || r)) {
            var o = !(t && t.silentJSONParsing) && r;
            try {
              return JSON.parse(e)
            } catch (e) {
              if (o) {
                if ("SyntaxError" === e.name) throw M.from(e, M.ERR_BAD_RESPONSE, this, null, this.response);
                throw e
              }
            }
          }
          return e
        }], timeout: 0, xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", maxContentLength: -1, maxBodyLength: -1, env: {FormData: re.classes.FormData, Blob: re.classes.Blob}, validateStatus: function (e) {
          return e >= 200 && e < 300
        }, headers: {common: {Accept: "application/json, text/plain, */*"}}
      };
      q.forEach(["delete", "get", "head"], function (e) {
        ae.headers[e] = {}
      }), q.forEach(["post", "put", "patch"], function (e) {
        ae.headers[e] = q.merge(ie)
      });
      var se = ae,
        ue = q.toObjectSet(["age", "authorization", "content-length", "content-type", "etag", "expires", "from", "host", "if-modified-since", "if-unmodified-since", "last-modified", "location", "max-forwards", "proxy-authorization", "referer", "retry-after", "user-agent"]),
        ce = Symbol("internals");

      function fe(e) {
        return e && String(e).trim().toLowerCase()
      }

      function le(e) {
        return !1 === e || null == e ? e : q.isArray(e) ? e.map(le) : String(e)
      }

      function de(e, t, n, r, o) {
        return q.isFunction(r) ? r.call(this, t, n) : (o && (t = n), q.isString(t) ? q.isString(r) ? -1 !== t.indexOf(r) : q.isRegExp(r) ? r.test(t) : void 0 : void 0)
      }

      var pe = function (e, n) {
        function i(e) {
          t(this, i), e && this.set(e)
        }

        return r(i, [{
          key: "set", value: function (e, t, n) {
            var r = this;

            function o(e, t, n) {
              var o = fe(t);
              if (!o) throw new Error("header name must be a non-empty string");
              var i = q.findKey(r, o);
              (!i || void 0 === r[i] || !0 === n || void 0 === n && !1 !== r[i]) && (r[i || t] = le(e))
            }

            var i, a, s, u, c, f = function (e, t) {
              return q.forEach(e, function (e, n) {
                return o(e, n, t)
              })
            };
            return q.isPlainObject(e) || e instanceof this.constructor ? f(e, t) : q.isString(e) && (e = e.trim()) && !/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim()) ? f((c = {}, (i = e) && i.split("\n").forEach(function (e) {
              u = e.indexOf(":"), a = e.substring(0, u).trim().toLowerCase(), s = e.substring(u + 1).trim(), !a || c[a] && ue[a] || ("set-cookie" === a ? c[a] ? c[a].push(s) : c[a] = [s] : c[a] = c[a] ? c[a] + ", " + s : s)
            }), c), t) : null != e && o(t, e, n), this
          }
        }, {
          key: "get", value: function (e, t) {
            if (e = fe(e)) {
              var n = q.findKey(this, e);
              if (n) {
                var r = this[n];
                if (!t) return r;
                if (!0 === t) return function (e) {
                  for (var t, n = Object.create(null), r = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; t = r.exec(e);) n[t[1]] = t[2];
                  return n
                }(r);
                if (q.isFunction(t)) return t.call(this, r, n);
                if (q.isRegExp(t)) return t.exec(r);
                throw new TypeError("parser must be boolean|regexp|function")
              }
            }
          }
        }, {
          key: "has", value: function (e, t) {
            if (e = fe(e)) {
              var n = q.findKey(this, e);
              return !(!n || void 0 === this[n] || t && !de(0, this[n], n, t))
            }
            return !1
          }
        }, {
          key: "delete", value: function (e, t) {
            var n = this, r = !1;

            function o(e) {
              if (e = fe(e)) {
                var o = q.findKey(n, e);
                !o || t && !de(0, n[o], o, t) || (delete n[o], r = !0)
              }
            }

            return q.isArray(e) ? e.forEach(o) : o(e), r
          }
        }, {
          key: "clear", value: function (e) {
            for (var t = Object.keys(this), n = t.length, r = !1; n--;) {
              var o = t[n];
              e && !de(0, this[o], o, e, !0) || (delete this[o], r = !0)
            }
            return r
          }
        }, {
          key: "normalize", value: function (e) {
            var t = this, n = {};
            return q.forEach(this, function (r, o) {
              var i = q.findKey(n, o);
              if (i) return t[i] = le(r), void delete t[o];
              var a = e ? function (e) {
                return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g, function (e, t, n) {
                  return t.toUpperCase() + n
                })
              }(o) : String(o).trim();
              a !== o && delete t[o], t[a] = le(r), n[a] = !0
            }), this
          }
        }, {
          key: "concat", value: function () {
            for (var e, t = arguments.length, n = new Array(t), r = 0; r < t; r++) n[r] = arguments[r];
            return (e = this.constructor).concat.apply(e, [this].concat(n))
          }
        }, {
          key: "toJSON", value: function (e) {
            var t = Object.create(null);
            return q.forEach(this, function (n, r) {
              null != n && !1 !== n && (t[r] = e && q.isArray(n) ? n.join(", ") : n)
            }), t
          }
        }, {
          key: Symbol.iterator, value: function () {
            return Object.entries(this.toJSON())[Symbol.iterator]()
          }
        }, {
          key: "toString", value: function () {
            return Object.entries(this.toJSON()).map(function (e) {
              var t = o(e, 2);
              return t[0] + ": " + t[1]
            }).join("\n")
          }
        }, {
          key: Symbol.toStringTag, get: function () {
            return "AxiosHeaders"
          }
        }], [{
          key: "from", value: function (e) {
            return e instanceof this ? e : new this(e)
          }
        }, {
          key: "concat", value: function (e) {
            for (var t = new this(e), n = arguments.length, r = new Array(n > 1 ? n - 1 : 0), o = 1; o < n; o++) r[o - 1] = arguments[o];
            return r.forEach(function (e) {
              return t.set(e)
            }), t
          }
        }, {
          key: "accessor", value: function (e) {
            var t = (this[ce] = this[ce] = {accessors: {}}).accessors, n = this.prototype;

            function r(e) {
              var r = fe(e);
              t[r] || (!function (e, t) {
                var n = q.toCamelCase(" " + t);
                ["get", "set", "has"].forEach(function (r) {
                  Object.defineProperty(e, r + n, {
                    value: function (e, n, o) {
                      return this[r].call(this, t, e, n, o)
                    }, configurable: !0
                  })
                })
              }(n, e), t[r] = !0)
            }

            return q.isArray(e) ? e.forEach(r) : r(e), this
          }
        }]), i
      }();
      pe.accessor(["Content-Type", "Content-Length", "Accept", "Accept-Encoding", "User-Agent", "Authorization"]), q.freezeMethods(pe.prototype), q.freezeMethods(pe);
      var he = pe;

      function me(e, t) {
        var n = this || se, r = t || n, o = he.from(r.headers), i = r.data;
        return q.forEach(e, function (e) {
          i = e.call(n, i, o.normalize(), t ? t.status : void 0)
        }), o.normalize(), i
      }

      function ye(e) {
        return !(!e || !e.__CANCEL__)
      }

      function ve(e, t, n) {
        M.call(this, null == e ? "canceled" : e, M.ERR_CANCELED, t, n), this.name = "CanceledError"
      }

      q.inherits(ve, M, {__CANCEL__: !0});
      var be = re.isStandardBrowserEnv ? {
        write: function (e, t, n, r, o, i) {
          var a = [];
          a.push(e + "=" + encodeURIComponent(t)), q.isNumber(n) && a.push("expires=" + new Date(n).toGMTString()), q.isString(r) && a.push("path=" + r), q.isString(o) && a.push("domain=" + o), !0 === i && a.push("secure"), document.cookie = a.join("; ")
        }, read: function (e) {
          var t = document.cookie.match(new RegExp("(^|;\\s*)(" + e + ")=([^;]*)"));
          return t ? decodeURIComponent(t[3]) : null
        }, remove: function (e) {
          this.write(e, "", Date.now() - 864e5)
        }
      } : {
        write: function () {
        }, read: function () {
          return null
        }, remove: function () {
        }
      };

      function ge(e, t) {
        return e && !/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t) ? function (e, t) {
          return t ? e.replace(/\/+$/, "") + "/" + t.replace(/^\/+/, "") : e
        }(e, t) : t
      }

      var we = re.isStandardBrowserEnv ? function () {
        var e, t = /(msie|trident)/i.test(navigator.userAgent), n = document.createElement("a");

        function r(e) {
          var r = e;
          return t && (n.setAttribute("href", r), r = n.href), n.setAttribute("href", r), {
            href: n.href,
            protocol: n.protocol ? n.protocol.replace(/:$/, "") : "",
            host: n.host,
            search: n.search ? n.search.replace(/^\?/, "") : "",
            hash: n.hash ? n.hash.replace(/^#/, "") : "",
            hostname: n.hostname,
            port: n.port,
            pathname: "/" === n.pathname.charAt(0) ? n.pathname : "/" + n.pathname
          }
        }

        return e = r(window.location.href), function (t) {
          var n = q.isString(t) ? r(t) : t;
          return n.protocol === e.protocol && n.host === e.host
        }
      }() : function () {
        return !0
      };

      function Ee(e, t) {
        var n = 0, r = function (e, t) {
          e = e || 10;
          var n, r = new Array(e), o = new Array(e), i = 0, a = 0;
          return t = void 0 !== t ? t : 1e3, function (s) {
            var u = Date.now(), c = o[a];
            n || (n = u), r[i] = s, o[i] = u;
            for (var f = a, l = 0; f !== i;) l += r[f++], f %= e;
            if ((i = (i + 1) % e) === a && (a = (a + 1) % e), !(u - n < t)) {
              var d = c && u - c;
              return d ? Math.round(1e3 * l / d) : void 0
            }
          }
        }(50, 250);
        return function (o) {
          var i = o.loaded, a = o.lengthComputable ? o.total : void 0, s = i - n, u = r(s);
          n = i;
          var c = {loaded: i, total: a, progress: a ? i / a : void 0, bytes: s, rate: u || void 0, estimated: u && a && i <= a ? (a - i) / u : void 0, event: o};
          c[t ? "download" : "upload"] = !0, e(c)
        }
      }

      var Oe = {
        http: null, xhr: "undefined" != typeof XMLHttpRequest && function (e) {
          return new Promise(function (t, n) {
            var r, o = e.data, i = he.from(e.headers).normalize(), a = e.responseType;

            function s() {
              e.cancelToken && e.cancelToken.unsubscribe(r), e.signal && e.signal.removeEventListener("abort", r)
            }

            q.isFormData(o) && (re.isStandardBrowserEnv || re.isStandardBrowserWebWorkerEnv ? i.setContentType(!1) : i.setContentType("multipart/form-data;", !1));
            var u = new XMLHttpRequest;
            if (e.auth) {
              var c = e.auth.username || "", f = e.auth.password ? unescape(encodeURIComponent(e.auth.password)) : "";
              i.set("Authorization", "Basic " + btoa(c + ":" + f))
            }
            var l = ge(e.baseURL, e.url);

            function d() {
              if (u) {
                var r = he.from("getAllResponseHeaders" in u && u.getAllResponseHeaders());
                !function (e, t, n) {
                  var r = n.config.validateStatus;
                  n.status && r && !r(n.status) ? t(new M("Request failed with status code " + n.status, [M.ERR_BAD_REQUEST, M.ERR_BAD_RESPONSE][Math.floor(n.status / 100) - 4], n.config, n.request, n)) : e(n)
                }(function (e) {
                  t(e), s()
                }, function (e) {
                  n(e), s()
                }, {data: a && "text" !== a && "json" !== a ? u.response : u.responseText, status: u.status, statusText: u.statusText, headers: r, config: e, request: u}), u = null
              }
            }

            if (u.open(e.method.toUpperCase(), Y(l, e.params, e.paramsSerializer), !0), u.timeout = e.timeout, "onloadend" in u ? u.onloadend = d : u.onreadystatechange = function () {
              u && 4 === u.readyState && (0 !== u.status || u.responseURL && 0 === u.responseURL.indexOf("file:")) && setTimeout(d)
            }, u.onabort = function () {
              u && (n(new M("Request aborted", M.ECONNABORTED, e, u)), u = null)
            }, u.onerror = function () {
              n(new M("Network Error", M.ERR_NETWORK, e, u)), u = null
            }, u.ontimeout = function () {
              var t = e.timeout ? "timeout of " + e.timeout + "ms exceeded" : "timeout exceeded", r = e.transitional || ne;
              e.timeoutErrorMessage && (t = e.timeoutErrorMessage), n(new M(t, r.clarifyTimeoutError ? M.ETIMEDOUT : M.ECONNABORTED, e, u)), u = null
            }, re.isStandardBrowserEnv) {
              var p = (e.withCredentials || we(l)) && e.xsrfCookieName && be.read(e.xsrfCookieName);
              p && i.set(e.xsrfHeaderName, p)
            }
            void 0 === o && i.setContentType(null), "setRequestHeader" in u && q.forEach(i.toJSON(), function (e, t) {
              u.setRequestHeader(t, e)
            }), q.isUndefined(e.withCredentials) || (u.withCredentials = !!e.withCredentials), a && "json" !== a && (u.responseType = e.responseType), "function" == typeof e.onDownloadProgress && u.addEventListener("progress", Ee(e.onDownloadProgress, !0)), "function" == typeof e.onUploadProgress && u.upload && u.upload.addEventListener("progress", Ee(e.onUploadProgress)), (e.cancelToken || e.signal) && (r = function (t) {
              u && (n(!t || t.type ? new ve(null, e, u) : t), u.abort(), u = null)
            }, e.cancelToken && e.cancelToken.subscribe(r), e.signal && (e.signal.aborted ? r() : e.signal.addEventListener("abort", r)));
            var h, m = (h = /^([-+\w]{1,25})(:?\/\/|:)/.exec(l)) && h[1] || "";
            m && -1 === re.protocols.indexOf(m) ? n(new M("Unsupported protocol " + m + ":", M.ERR_BAD_REQUEST, e)) : u.send(o || null)
          })
        }
      };
      q.forEach(Oe, function (e, t) {
        if (e) {
          try {
            Object.defineProperty(e, "name", {value: t})
          } catch (e) {
          }
          Object.defineProperty(e, "adapterName", {value: t})
        }
      });
      var Se = function (e) {
        for (var t, n, r = (e = q.isArray(e) ? e : [e]).length, o = 0; o < r && (t = e[o], !(n = q.isString(t) ? Oe[t.toLowerCase()] : t)); o++) ;
        if (!n) {
          if (!1 === n) throw new M("Adapter ".concat(t, " is not supported by the environment"), "ERR_NOT_SUPPORT");
          throw new Error(q.hasOwnProp(Oe, t) ? "Adapter '".concat(t, "' is not available in the build") : "Unknown adapter '".concat(t, "'"))
        }
        if (!q.isFunction(n)) throw new TypeError("adapter is not a function");
        return n
      };

      function Re(e) {
        if (e.cancelToken && e.cancelToken.throwIfRequested(), e.signal && e.signal.aborted) throw new ve(null, e)
      }

      function Ae(e) {
        return Re(e), e.headers = he.from(e.headers), e.data = me.call(e, e.transformRequest), -1 !== ["post", "put", "patch"].indexOf(e.method) && e.headers.setContentType("application/x-www-form-urlencoded", !1), Se(e.adapter || se.adapter)(e).then(function (t) {
          return Re(e), t.data = me.call(e, e.transformResponse, t), t.headers = he.from(t.headers), t
        }, function (t) {
          return ye(t) || (Re(e), t && t.response && (t.response.data = me.call(e, e.transformResponse, t.response), t.response.headers = he.from(t.response.headers))), Promise.reject(t)
        })
      }

      var Te = function (e) {
        return e instanceof he ? e.toJSON() : e
      };

      function je(e, t) {
        t = t || {};
        var n = {};

        function r(e, t, n) {
          return q.isPlainObject(e) && q.isPlainObject(t) ? q.merge.call({caseless: n}, e, t) : q.isPlainObject(t) ? q.merge({}, t) : q.isArray(t) ? t.slice() : t
        }

        function o(e, t, n) {
          return q.isUndefined(t) ? q.isUndefined(e) ? void 0 : r(void 0, e, n) : r(e, t, n)
        }

        function i(e, t) {
          if (!q.isUndefined(t)) return r(void 0, t)
        }

        function a(e, t) {
          return q.isUndefined(t) ? q.isUndefined(e) ? void 0 : r(void 0, e) : r(void 0, t)
        }

        function s(n, o, i) {
          return i in t ? r(n, o) : i in e ? r(void 0, n) : void 0
        }

        var u = {
          url: i,
          method: i,
          data: i,
          baseURL: a,
          transformRequest: a,
          transformResponse: a,
          paramsSerializer: a,
          timeout: a,
          timeoutMessage: a,
          withCredentials: a,
          adapter: a,
          responseType: a,
          xsrfCookieName: a,
          xsrfHeaderName: a,
          onUploadProgress: a,
          onDownloadProgress: a,
          decompress: a,
          maxContentLength: a,
          maxBodyLength: a,
          beforeRedirect: a,
          transport: a,
          httpAgent: a,
          httpsAgent: a,
          cancelToken: a,
          socketPath: a,
          responseEncoding: a,
          validateStatus: s,
          headers: function (e, t) {
            return o(Te(e), Te(t), !0)
          }
        };
        return q.forEach(Object.keys(Object.assign({}, e, t)), function (r) {
          var i = u[r] || o, a = i(e[r], t[r], r);
          q.isUndefined(a) && i !== s || (n[r] = a)
        }), n
      }

      var Ne = "1.4.0", Ce = {};
      ["object", "boolean", "number", "function", "string", "symbol"].forEach(function (t, n) {
        Ce[t] = function (r) {
          return e(r) === t || "a" + (n < 1 ? "n " : " ") + t
        }
      });
      var xe = {};
      Ce.transitional = function (e, t, n) {
        function r(e, t) {
          return "[Axios v1.4.0] Transitional option '" + e + "'" + t + (n ? ". " + n : "")
        }

        return function (n, o, i) {
          if (!1 === e) throw new M(r(o, " has been removed" + (t ? " in " + t : "")), M.ERR_DEPRECATED);
          return t && !xe[o] && (xe[o] = !0, console.warn(r(o, " has been deprecated since v" + t + " and will be removed in the near future"))), !e || e(n, o, i)
        }
      };
      var Pe = {
        assertOptions: function (t, n, r) {
          if ("object" !== e(t)) throw new M("options must be an object", M.ERR_BAD_OPTION_VALUE);
          for (var o = Object.keys(t), i = o.length; i-- > 0;) {
            var a = o[i], s = n[a];
            if (s) {
              var u = t[a], c = void 0 === u || s(u, a, t);
              if (!0 !== c) throw new M("option " + a + " must be " + c, M.ERR_BAD_OPTION_VALUE)
            } else if (!0 !== r) throw new M("Unknown option " + a, M.ERR_BAD_OPTION)
          }
        }, validators: Ce
      }, ke = Pe.validators, Ue = function () {
        function e(n) {
          t(this, e), this.defaults = n, this.interceptors = {request: new te, response: new te}
        }

        return r(e, [{
          key: "request", value: function (e, t) {
            "string" == typeof e ? (t = t || {}).url = e : t = e || {};
            var n, r = t = je(this.defaults, t), o = r.transitional, i = r.paramsSerializer, a = r.headers;
            void 0 !== o && Pe.assertOptions(o, {
              silentJSONParsing: ke.transitional(ke.boolean),
              forcedJSONParsing: ke.transitional(ke.boolean),
              clarifyTimeoutError: ke.transitional(ke.boolean)
            }, !1), null != i && (q.isFunction(i) ? t.paramsSerializer = {serialize: i} : Pe.assertOptions(i, {
              encode: ke.function,
              serialize: ke.function
            }, !0)), t.method = (t.method || this.defaults.method || "get").toLowerCase(), (n = a && q.merge(a.common, a[t.method])) && q.forEach(["delete", "get", "head", "post", "put", "patch", "common"], function (e) {
              delete a[e]
            }), t.headers = he.concat(n, a);
            var s = [], u = !0;
            this.interceptors.request.forEach(function (e) {
              "function" == typeof e.runWhen && !1 === e.runWhen(t) || (u = u && e.synchronous, s.unshift(e.fulfilled, e.rejected))
            });
            var c, f = [];
            this.interceptors.response.forEach(function (e) {
              f.push(e.fulfilled, e.rejected)
            });
            var l, d = 0;
            if (!u) {
              var p = [Ae.bind(this), void 0];
              for (p.unshift.apply(p, s), p.push.apply(p, f), l = p.length, c = Promise.resolve(t); d < l;) c = c.then(p[d++], p[d++]);
              return c
            }
            l = s.length;
            var h = t;
            for (d = 0; d < l;) {
              var m = s[d++], y = s[d++];
              try {
                h = m(h)
              } catch (e) {
                y.call(this, e);
                break
              }
            }
            try {
              c = Ae.call(this, h)
            } catch (e) {
              return Promise.reject(e)
            }
            for (d = 0, l = f.length; d < l;) c = c.then(f[d++], f[d++]);
            return c
          }
        }, {
          key: "getUri", value: function (e) {
            return Y(ge((e = je(this.defaults, e)).baseURL, e.url), e.params, e.paramsSerializer)
          }
        }]), e
      }();
      q.forEach(["delete", "get", "head", "options"], function (e) {
        Ue.prototype[e] = function (t, n) {
          return this.request(je(n || {}, {method: e, url: t, data: (n || {}).data}))
        }
      }), q.forEach(["post", "put", "patch"], function (e) {
        function t(t) {
          return function (n, r, o) {
            return this.request(je(o || {}, {method: e, headers: t ? {"Content-Type": "multipart/form-data"} : {}, url: n, data: r}))
          }
        }

        Ue.prototype[e] = t(), Ue.prototype[e + "Form"] = t(!0)
      });
      var _e = Ue, Fe = function () {
        function e(n) {
          if (t(this, e), "function" != typeof n) throw new TypeError("executor must be a function.");
          var r;
          this.promise = new Promise(function (e) {
            r = e
          });
          var o = this;
          this.promise.then(function (e) {
            if (o._listeners) {
              for (var t = o._listeners.length; t-- > 0;) o._listeners[t](e);
              o._listeners = null
            }
          }), this.promise.then = function (e) {
            var t, n = new Promise(function (e) {
              o.subscribe(e), t = e
            }).then(e);
            return n.cancel = function () {
              o.unsubscribe(t)
            }, n
          }, n(function (e, t, n) {
            o.reason || (o.reason = new ve(e, t, n), r(o.reason))
          })
        }

        return r(e, [{
          key: "throwIfRequested", value: function () {
            if (this.reason) throw this.reason
          }
        }, {
          key: "subscribe", value: function (e) {
            this.reason ? e(this.reason) : this._listeners ? this._listeners.push(e) : this._listeners = [e]
          }
        }, {
          key: "unsubscribe", value: function (e) {
            if (this._listeners) {
              var t = this._listeners.indexOf(e);
              -1 !== t && this._listeners.splice(t, 1)
            }
          }
        }], [{
          key: "source", value: function () {
            var t;
            return {
              token: new e(function (e) {
                t = e
              }), cancel: t
            }
          }
        }]), e
      }();
      var Be = {
        Continue: 100,
        SwitchingProtocols: 101,
        Processing: 102,
        EarlyHints: 103,
        Ok: 200,
        Created: 201,
        Accepted: 202,
        NonAuthoritativeInformation: 203,
        NoContent: 204,
        ResetContent: 205,
        PartialContent: 206,
        MultiStatus: 207,
        AlreadyReported: 208,
        ImUsed: 226,
        MultipleChoices: 300,
        MovedPermanently: 301,
        Found: 302,
        SeeOther: 303,
        NotModified: 304,
        UseProxy: 305,
        Unused: 306,
        TemporaryRedirect: 307,
        PermanentRedirect: 308,
        BadRequest: 400,
        Unauthorized: 401,
        PaymentRequired: 402,
        Forbidden: 403,
        NotFound: 404,
        MethodNotAllowed: 405,
        NotAcceptable: 406,
        ProxyAuthenticationRequired: 407,
        RequestTimeout: 408,
        Conflict: 409,
        Gone: 410,
        LengthRequired: 411,
        PreconditionFailed: 412,
        PayloadTooLarge: 413,
        UriTooLong: 414,
        UnsupportedMediaType: 415,
        RangeNotSatisfiable: 416,
        ExpectationFailed: 417,
        ImATeapot: 418,
        MisdirectedRequest: 421,
        UnprocessableEntity: 422,
        Locked: 423,
        FailedDependency: 424,
        TooEarly: 425,
        UpgradeRequired: 426,
        PreconditionRequired: 428,
        TooManyRequests: 429,
        RequestHeaderFieldsTooLarge: 431,
        UnavailableForLegalReasons: 451,
        InternalServerError: 500,
        NotImplemented: 501,
        BadGateway: 502,
        ServiceUnavailable: 503,
        GatewayTimeout: 504,
        HttpVersionNotSupported: 505,
        VariantAlsoNegotiates: 506,
        InsufficientStorage: 507,
        LoopDetected: 508,
        NotExtended: 510,
        NetworkAuthenticationRequired: 511
      };
      Object.entries(Be).forEach(function (e) {
        var t = o(e, 2), n = t[0], r = t[1];
        Be[r] = n
      });
      var Le = Be;
      var De = function e(t) {
        var n = new _e(t), r = a(_e.prototype.request, n);
        return q.extend(r, _e.prototype, n, {allOwnKeys: !0}), q.extend(r, n, null, {allOwnKeys: !0}), r.create = function (n) {
          return e(je(t, n))
        }, r
      }(se);
      return De.Axios = _e, De.CanceledError = ve, De.CancelToken = Fe, De.isCancel = ye, De.VERSION = Ne, De.toFormData = G, De.AxiosError = M, De.Cancel = De.CanceledError, De.all = function (e) {
        return Promise.all(e)
      }, De.spread = function (e) {
        return function (t) {
          return e.apply(null, t)
        }
      }, De.isAxiosError = function (e) {
        return q.isObject(e) && !0 === e.isAxiosError
      }, De.mergeConfig = je, De.AxiosHeaders = he, De.formToJSON = function (e) {
        return oe(q.isHTMLForm(e) ? new FormData(e) : e)
      }, De.HttpStatusCode = Le, De.default = De, De
    });
    return {
      requestAction: function (me, action, config) {
        config.url = me.getActionUrl();
        config.method = "post";
        config.params = config.params || {};
        config.params = Object.assign(config.params, me.getOpt("serverparam"));
        config.params.action = action;
        return this.request(me, config)
      }, request: function (me, config) {
        config.headers = config.headers || {};
        var customHeaders = me.getOpt("serverHeaders");
        if (customHeaders) {
          for (var key in customHeaders) {
            config.headers[key] = customHeaders[key]
          }
        }
        return axios(config)
      }
    }
  }();
  UE.image = function () {
    var imageCompression = null;
    !function (e, t) {
      imageCompression = t()
    }(this, function () {
      "use strict";

      function _mergeNamespaces(e, t) {
        return t.forEach(function (t) {
          t && "string" != typeof t && !Array.isArray(t) && Object.keys(t).forEach(function (r) {
            if ("default" !== r && !(r in e)) {
              var i = Object.getOwnPropertyDescriptor(t, r);
              Object.defineProperty(e, r, i.get ? i : {
                enumerable: !0, get: function () {
                  return t[r]
                }
              })
            }
          })
        }), Object.freeze(e)
      }

      function copyExifWithoutOrientation(e, t) {
        return new Promise(function (r, i) {
          let o;
          return getApp1Segment(e).then(function (e) {
            try {
              return o = e, r(new Blob([t.slice(0, 2), o, t.slice(2)], {type: "image/jpeg"}))
            } catch (e) {
              return i(e)
            }
          }, i)
        })
      }

      const getApp1Segment = e => new Promise((t, r) => {
        const i = new FileReader;
        i.addEventListener("load", ({target: {result: e}}) => {
          const i = new DataView(e);
          let o = 0;
          if (65496 !== i.getUint16(o)) return r("not a valid JPEG");
          for (o += 2; ;) {
            const a = i.getUint16(o);
            if (65498 === a) break;
            const s = i.getUint16(o + 2);
            if (65505 === a && 1165519206 === i.getUint32(o + 4)) {
              const a = o + 10;
              let f;
              switch (i.getUint16(a)) {
                case 18761:
                  f = !0;
                  break;
                case 19789:
                  f = !1;
                  break;
                default:
                  return r("TIFF header contains invalid endian")
              }
              if (42 !== i.getUint16(a + 2, f)) return r("TIFF header contains invalid version");
              const l = i.getUint32(a + 4, f), c = a + l + 2 + 12 * i.getUint16(a + l, f);
              for (let e = a + l + 2; e < c; e += 12) {
                if (274 == i.getUint16(e, f)) {
                  if (3 !== i.getUint16(e + 2, f)) return r("Orientation data type is invalid");
                  if (1 !== i.getUint32(e + 4, f)) return r("Orientation data count is invalid");
                  i.setUint16(e + 8, 1, f);
                  break
                }
              }
              return t(e.slice(o, o + 2 + s))
            }
            o += 2 + s
          }
          return t(new Blob)
        }), i.readAsArrayBuffer(e)
      });
      var e = {};
      !function (e) {
        var t, r, UZIP = {};
        e.exports = UZIP, UZIP.parse = function (e, t) {
          for (var r = UZIP.bin.readUshort, i = UZIP.bin.readUint, o = 0, a = {}, s = new Uint8Array(e), f = s.length - 4; 101010256 != i(s, f);) f--;
          o = f;
          o += 4;
          var l = r(s, o += 4);
          r(s, o += 2);
          var c = i(s, o += 2), u = i(s, o += 4);
          o += 4, o = u;
          for (var h = 0; h < l; h++) {
            i(s, o), o += 4, o += 4, o += 4, i(s, o += 4);
            c = i(s, o += 4);
            var d = i(s, o += 4), A = r(s, o += 4), g = r(s, o + 2), p = r(s, o + 4);
            o += 6;
            var m = i(s, o += 8);
            o += 4, o += A + g + p, UZIP._readLocal(s, m, a, c, d, t)
          }
          return a
        }, UZIP._readLocal = function (e, t, r, i, o, a) {
          var s = UZIP.bin.readUshort, f = UZIP.bin.readUint;
          f(e, t), s(e, t += 4), s(e, t += 2);
          var l = s(e, t += 2);
          f(e, t += 2), f(e, t += 4), t += 4;
          var c = s(e, t += 8), u = s(e, t += 2);
          t += 2;
          var h = UZIP.bin.readUTF8(e, t, c);
          if (t += c, t += u, a) r[h] = {size: o, csize: i}; else {
            var d = new Uint8Array(e.buffer, t);
            if (0 == l) r[h] = new Uint8Array(d.buffer.slice(t, t + i)); else {
              if (8 != l) throw"unknown compression method: " + l;
              var A = new Uint8Array(o);
              UZIP.inflateRaw(d, A), r[h] = A
            }
          }
        }, UZIP.inflateRaw = function (e, t) {
          return UZIP.F.inflate(e, t)
        }, UZIP.inflate = function (e, t) {
          return e[0], e[1], UZIP.inflateRaw(new Uint8Array(e.buffer, e.byteOffset + 2, e.length - 6), t)
        }, UZIP.deflate = function (e, t) {
          null == t && (t = {level: 6});
          var r = 0, i = new Uint8Array(50 + Math.floor(1.1 * e.length));
          i[r] = 120, i[r + 1] = 156, r += 2, r = UZIP.F.deflateRaw(e, i, r, t.level);
          var o = UZIP.adler(e, 0, e.length);
          return i[r + 0] = o >>> 24 & 255, i[r + 1] = o >>> 16 & 255, i[r + 2] = o >>> 8 & 255, i[r + 3] = o >>> 0 & 255, new Uint8Array(i.buffer, 0, r + 4)
        }, UZIP.deflateRaw = function (e, t) {
          null == t && (t = {level: 6});
          var r = new Uint8Array(50 + Math.floor(1.1 * e.length)), i = UZIP.F.deflateRaw(e, r, i, t.level);
          return new Uint8Array(r.buffer, 0, i)
        }, UZIP.encode = function (e, t) {
          null == t && (t = !1);
          var r = 0, i = UZIP.bin.writeUint, o = UZIP.bin.writeUshort, a = {};
          for (var s in e) {
            var f = !UZIP._noNeed(s) && !t, l = e[s], c = UZIP.crc.crc(l, 0, l.length);
            a[s] = {cpr: f, usize: l.length, crc: c, file: f ? UZIP.deflateRaw(l) : l}
          }
          for (var s in a) r += a[s].file.length + 30 + 46 + 2 * UZIP.bin.sizeUTF8(s);
          r += 22;
          var u = new Uint8Array(r), h = 0, d = [];
          for (var s in a) {
            var A = a[s];
            d.push(h), h = UZIP._writeHeader(u, h, s, A, 0)
          }
          var g = 0, p = h;
          for (var s in a) {
            A = a[s];
            d.push(h), h = UZIP._writeHeader(u, h, s, A, 1, d[g++])
          }
          var m = h - p;
          return i(u, h, 101010256), h += 4, o(u, h += 4, g), o(u, h += 2, g), i(u, h += 2, m), i(u, h += 4, p), h += 4, h += 2, u.buffer
        }, UZIP._noNeed = function (e) {
          var t = e.split(".").pop().toLowerCase();
          return -1 != "png,jpg,jpeg,zip".indexOf(t)
        }, UZIP._writeHeader = function (e, t, r, i, o, a) {
          var s = UZIP.bin.writeUint, f = UZIP.bin.writeUshort, l = i.file;
          return s(e, t, 0 == o ? 67324752 : 33639248), t += 4, 1 == o && (t += 2), f(e, t, 20), f(e, t += 2, 0), f(e, t += 2, i.cpr ? 8 : 0), s(e, t += 2, 0), s(e, t += 4, i.crc), s(e, t += 4, l.length), s(e, t += 4, i.usize), f(e, t += 4, UZIP.bin.sizeUTF8(r)), f(e, t += 2, 0), t += 2, 1 == o && (t += 2, t += 2, s(e, t += 6, a), t += 4), t += UZIP.bin.writeUTF8(e, t, r), 0 == o && (e.set(l, t), t += l.length), t
        }, UZIP.crc = {
          table: function () {
            for (var e = new Uint32Array(256), t = 0; t < 256; t++) {
              for (var r = t, i = 0; i < 8; i++) 1 & r ? r = 3988292384 ^ r >>> 1 : r >>>= 1;
              e[t] = r
            }
            return e
          }(), update: function (e, t, r, i) {
            for (var o = 0; o < i; o++) e = UZIP.crc.table[255 & (e ^ t[r + o])] ^ e >>> 8;
            return e
          }, crc: function (e, t, r) {
            return 4294967295 ^ UZIP.crc.update(4294967295, e, t, r)
          }
        }, UZIP.adler = function (e, t, r) {
          for (var i = 1, o = 0, a = t, s = t + r; a < s;) {
            for (var f = Math.min(a + 5552, s); a < f;) o += i += e[a++];
            i %= 65521, o %= 65521
          }
          return o << 16 | i
        }, UZIP.bin = {
          readUshort: function (e, t) {
            return e[t] | e[t + 1] << 8
          }, writeUshort: function (e, t, r) {
            e[t] = 255 & r, e[t + 1] = r >> 8 & 255
          }, readUint: function (e, t) {
            return 16777216 * e[t + 3] + (e[t + 2] << 16 | e[t + 1] << 8 | e[t])
          }, writeUint: function (e, t, r) {
            e[t] = 255 & r, e[t + 1] = r >> 8 & 255, e[t + 2] = r >> 16 & 255, e[t + 3] = r >> 24 & 255
          }, readASCII: function (e, t, r) {
            for (var i = "", o = 0; o < r; o++) i += String.fromCharCode(e[t + o]);
            return i
          }, writeASCII: function (e, t, r) {
            for (var i = 0; i < r.length; i++) e[t + i] = r.charCodeAt(i)
          }, pad: function (e) {
            return e.length < 2 ? "0" + e : e
          }, readUTF8: function (e, t, r) {
            for (var i, o = "", a = 0; a < r; a++) o += "%" + UZIP.bin.pad(e[t + a].toString(16));
            try {
              i = decodeURIComponent(o)
            } catch (i) {
              return UZIP.bin.readASCII(e, t, r)
            }
            return i
          }, writeUTF8: function (e, t, r) {
            for (var i = r.length, o = 0, a = 0; a < i; a++) {
              var s = r.charCodeAt(a);
              if (0 == (4294967168 & s)) e[t + o] = s, o++; else if (0 == (4294965248 & s)) e[t + o] = 192 | s >> 6, e[t + o + 1] = 128 | s >> 0 & 63, o += 2; else if (0 == (4294901760 & s)) e[t + o] = 224 | s >> 12, e[t + o + 1] = 128 | s >> 6 & 63, e[t + o + 2] = 128 | s >> 0 & 63, o += 3; else {
                if (0 != (4292870144 & s)) throw"e";
                e[t + o] = 240 | s >> 18, e[t + o + 1] = 128 | s >> 12 & 63, e[t + o + 2] = 128 | s >> 6 & 63, e[t + o + 3] = 128 | s >> 0 & 63, o += 4
              }
            }
            return o
          }, sizeUTF8: function (e) {
            for (var t = e.length, r = 0, i = 0; i < t; i++) {
              var o = e.charCodeAt(i);
              if (0 == (4294967168 & o)) r++; else if (0 == (4294965248 & o)) r += 2; else if (0 == (4294901760 & o)) r += 3; else {
                if (0 != (4292870144 & o)) throw"e";
                r += 4
              }
            }
            return r
          }
        }, UZIP.F = {}, UZIP.F.deflateRaw = function (e, t, r, i) {
          var o = [[0, 0, 0, 0, 0], [4, 4, 8, 4, 0], [4, 5, 16, 8, 0], [4, 6, 16, 16, 0], [4, 10, 16, 32, 0], [8, 16, 32, 32, 0], [8, 16, 128, 128, 0], [8, 32, 128, 256, 0], [32, 128, 258, 1024, 1], [32, 258, 258, 4096, 1]][i], a = UZIP.F.U,
            s = UZIP.F._goodIndex;
          UZIP.F._hash;
          var f = UZIP.F._putsE, l = 0, c = r << 3, u = 0, h = e.length;
          if (0 == i) {
            for (; l < h;) {
              f(t, c, l + (_ = Math.min(65535, h - l)) == h ? 1 : 0), c = UZIP.F._copyExact(e, l, _, t, c + 8), l += _
            }
            return c >>> 3
          }
          var d = a.lits, A = a.strt, g = a.prev, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0;
          for (h > 2 && (A[y = UZIP.F._hash(e, 0)] = 0), l = 0; l < h; l++) {
            if (b = y, l + 1 < h - 2) {
              y = UZIP.F._hash(e, l + 1);
              var E = l + 1 & 32767;
              g[E] = A[y], A[y] = E
            }
            if (u <= l) {
              (p > 14e3 || m > 26697) && h - l > 100 && (u < l && (d[p] = l - u, p += 2, u = l), c = UZIP.F._writeBlock(l == h - 1 || u == h ? 1 : 0, d, p, v, e, w, l - w, t, c), p = m = v = 0, w = l);
              var F = 0;
              l < h - 2 && (F = UZIP.F._bestMatch(e, l, g, b, Math.min(o[2], h - l), o[3]));
              var _ = F >>> 16, B = 65535 & F;
              if (0 != F) {
                B = 65535 & F;
                var U = s(_ = F >>> 16, a.of0);
                a.lhst[257 + U]++;
                var C = s(B, a.df0);
                a.dhst[C]++, v += a.exb[U] + a.dxb[C], d[p] = _ << 23 | l - u, d[p + 1] = B << 16 | U << 8 | C, p += 2, u = l + _
              } else a.lhst[e[l]]++;
              m++
            }
          }
          for (w == l && 0 != e.length || (u < l && (d[p] = l - u, p += 2, u = l), c = UZIP.F._writeBlock(1, d, p, v, e, w, l - w, t, c), p = 0, m = 0, p = m = v = 0, w = l); 0 != (7 & c);) c++;
          return c >>> 3
        }, UZIP.F._bestMatch = function (e, t, r, i, o, a) {
          var s = 32767 & t, f = r[s], l = s - f + 32768 & 32767;
          if (f == s || i != UZIP.F._hash(e, t - l)) return 0;
          for (var c = 0, u = 0, h = Math.min(32767, t); l <= h && 0 != --a && f != s;) {
            if (0 == c || e[t + c] == e[t + c - l]) {
              var d = UZIP.F._howLong(e, t, l);
              if (d > c) {
                if (u = l, (c = d) >= o) break;
                l + 2 < d && (d = l + 2);
                for (var A = 0, g = 0; g < d - 2; g++) {
                  var p = t - l + g + 32768 & 32767, m = p - r[p] + 32768 & 32767;
                  m > A && (A = m, f = p)
                }
              }
            }
            l += (s = f) - (f = r[s]) + 32768 & 32767
          }
          return c << 16 | u
        }, UZIP.F._howLong = function (e, t, r) {
          if (e[t] != e[t - r] || e[t + 1] != e[t + 1 - r] || e[t + 2] != e[t + 2 - r]) return 0;
          var i = t, o = Math.min(e.length, t + 258);
          for (t += 3; t < o && e[t] == e[t - r];) t++;
          return t - i
        }, UZIP.F._hash = function (e, t) {
          return (e[t] << 8 | e[t + 1]) + (e[t + 2] << 4) & 65535
        }, UZIP.saved = 0, UZIP.F._writeBlock = function (e, t, r, i, o, a, s, f, l) {
          var c, u, h, d, A, g, p, m, w, v = UZIP.F.U, b = UZIP.F._putsF, y = UZIP.F._putsE;
          v.lhst[256]++, u = (c = UZIP.F.getTrees())[0], h = c[1], d = c[2], A = c[3], g = c[4], p = c[5], m = c[6], w = c[7];
          var E = 32 + (0 == (l + 3 & 7) ? 0 : 8 - (l + 3 & 7)) + (s << 3), F = i + UZIP.F.contSize(v.fltree, v.lhst) + UZIP.F.contSize(v.fdtree, v.dhst), _ = i + UZIP.F.contSize(v.ltree, v.lhst) + UZIP.F.contSize(v.dtree, v.dhst);
          _ += 14 + 3 * p + UZIP.F.contSize(v.itree, v.ihst) + (2 * v.ihst[16] + 3 * v.ihst[17] + 7 * v.ihst[18]);
          for (var B = 0; B < 286; B++) v.lhst[B] = 0;
          for (B = 0; B < 30; B++) v.dhst[B] = 0;
          for (B = 0; B < 19; B++) v.ihst[B] = 0;
          var U = E < F && E < _ ? 0 : F < _ ? 1 : 2;
          if (b(f, l, e), b(f, l + 1, U), l += 3, 0 == U) {
            for (; 0 != (7 & l);) l++;
            l = UZIP.F._copyExact(o, a, s, f, l)
          } else {
            var C, I;
            if (1 == U && (C = v.fltree, I = v.fdtree), 2 == U) {
              UZIP.F.makeCodes(v.ltree, u), UZIP.F.revCodes(v.ltree, u), UZIP.F.makeCodes(v.dtree, h), UZIP.F.revCodes(v.dtree, h), UZIP.F.makeCodes(v.itree, d), UZIP.F.revCodes(v.itree, d), C = v.ltree, I = v.dtree, y(f, l, A - 257), y(f, l += 5, g - 1), y(f, l += 5, p - 4), l += 4;
              for (var Q = 0; Q < p; Q++) y(f, l + 3 * Q, v.itree[1 + (v.ordr[Q] << 1)]);
              l += 3 * p, l = UZIP.F._codeTiny(m, v.itree, f, l), l = UZIP.F._codeTiny(w, v.itree, f, l)
            }
            for (var M = a, x = 0; x < r; x += 2) {
              for (var T = t[x], S = T >>> 23, R = M + (8388607 & T); M < R;) l = UZIP.F._writeLit(o[M++], C, f, l);
              if (0 != S) {
                var O = t[x + 1], P = O >> 16, H = O >> 8 & 255, L = 255 & O;
                y(f, l = UZIP.F._writeLit(257 + H, C, f, l), S - v.of0[H]), l += v.exb[H], b(f, l = UZIP.F._writeLit(L, I, f, l), P - v.df0[L]), l += v.dxb[L], M += S
              }
            }
            l = UZIP.F._writeLit(256, C, f, l)
          }
          return l
        }, UZIP.F._copyExact = function (e, t, r, i, o) {
          var a = o >>> 3;
          return i[a] = r, i[a + 1] = r >>> 8, i[a + 2] = 255 - i[a], i[a + 3] = 255 - i[a + 1], a += 4, i.set(new Uint8Array(e.buffer, t, r), a), o + (r + 4 << 3)
        }, UZIP.F.getTrees = function () {
          for (var e = UZIP.F.U, t = UZIP.F._hufTree(e.lhst, e.ltree, 15), r = UZIP.F._hufTree(e.dhst, e.dtree, 15), i = [], o = UZIP.F._lenCodes(e.ltree, i), a = [], s = UZIP.F._lenCodes(e.dtree, a), f = 0; f < i.length; f += 2) e.ihst[i[f]]++;
          for (f = 0; f < a.length; f += 2) e.ihst[a[f]]++;
          for (var l = UZIP.F._hufTree(e.ihst, e.itree, 7), c = 19; c > 4 && 0 == e.itree[1 + (e.ordr[c - 1] << 1)];) c--;
          return [t, r, l, o, s, c, i, a]
        }, UZIP.F.getSecond = function (e) {
          for (var t = [], r = 0; r < e.length; r += 2) t.push(e[r + 1]);
          return t
        }, UZIP.F.nonZero = function (e) {
          for (var t = "", r = 0; r < e.length; r += 2) 0 != e[r + 1] && (t += (r >> 1) + ",");
          return t
        }, UZIP.F.contSize = function (e, t) {
          for (var r = 0, i = 0; i < t.length; i++) r += t[i] * e[1 + (i << 1)];
          return r
        }, UZIP.F._codeTiny = function (e, t, r, i) {
          for (var o = 0; o < e.length; o += 2) {
            var a = e[o], s = e[o + 1];
            i = UZIP.F._writeLit(a, t, r, i);
            var f = 16 == a ? 2 : 17 == a ? 3 : 7;
            a > 15 && (UZIP.F._putsE(r, i, s, f), i += f)
          }
          return i
        }, UZIP.F._lenCodes = function (e, t) {
          for (var r = e.length; 2 != r && 0 == e[r - 1];) r -= 2;
          for (var i = 0; i < r; i += 2) {
            var o = e[i + 1], a = i + 3 < r ? e[i + 3] : -1, s = i + 5 < r ? e[i + 5] : -1, f = 0 == i ? -1 : e[i - 1];
            if (0 == o && a == o && s == o) {
              for (var l = i + 5; l + 2 < r && e[l + 2] == o;) l += 2;
              (c = Math.min(l + 1 - i >>> 1, 138)) < 11 ? t.push(17, c - 3) : t.push(18, c - 11), i += 2 * c - 2
            } else if (o == f && a == o && s == o) {
              for (l = i + 5; l + 2 < r && e[l + 2] == o;) l += 2;
              var c = Math.min(l + 1 - i >>> 1, 6);
              t.push(16, c - 3), i += 2 * c - 2
            } else t.push(o, 0)
          }
          return r >>> 1
        }, UZIP.F._hufTree = function (e, t, r) {
          var i = [], o = e.length, a = t.length, s = 0;
          for (s = 0; s < a; s += 2) t[s] = 0, t[s + 1] = 0;
          for (s = 0; s < o; s++) 0 != e[s] && i.push({lit: s, f: e[s]});
          var f = i.length, l = i.slice(0);
          if (0 == f) return 0;
          if (1 == f) {
            var c = i[0].lit;
            l = 0 == c ? 1 : 0;
            return t[1 + (c << 1)] = 1, t[1 + (l << 1)] = 1, 1
          }
          i.sort(function (e, t) {
            return e.f - t.f
          });
          var u = i[0], h = i[1], d = 0, A = 1, g = 2;
          for (i[0] = {lit: -1, f: u.f + h.f, l: u, r: h, d: 0}; A != f - 1;) u = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++], h = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++], i[A++] = {lit: -1, f: u.f + h.f, l: u, r: h};
          var p = UZIP.F.setDepth(i[A - 1], 0);
          for (p > r && (UZIP.F.restrictDepth(l, r, p), p = r), s = 0; s < f; s++) t[1 + (l[s].lit << 1)] = l[s].d;
          return p
        }, UZIP.F.setDepth = function (e, t) {
          return -1 != e.lit ? (e.d = t, t) : Math.max(UZIP.F.setDepth(e.l, t + 1), UZIP.F.setDepth(e.r, t + 1))
        }, UZIP.F.restrictDepth = function (e, t, r) {
          var i = 0, o = 1 << r - t, a = 0;
          for (e.sort(function (e, t) {
            return t.d == e.d ? e.f - t.f : t.d - e.d
          }), i = 0; i < e.length && e[i].d > t; i++) {
            var s = e[i].d;
            e[i].d = t, a += o - (1 << r - s)
          }
          for (a >>>= r - t; a > 0;) {
            (s = e[i].d) < t ? (e[i].d++, a -= 1 << t - s - 1) : i++
          }
          for (; i >= 0; i--) e[i].d == t && a < 0 && (e[i].d--, a++);
          0 != a && console.log("debt left")
        }, UZIP.F._goodIndex = function (e, t) {
          var r = 0;
          return t[16 | r] <= e && (r |= 16), t[8 | r] <= e && (r |= 8), t[4 | r] <= e && (r |= 4), t[2 | r] <= e && (r |= 2), t[1 | r] <= e && (r |= 1), r
        }, UZIP.F._writeLit = function (e, t, r, i) {
          return UZIP.F._putsF(r, i, t[e << 1]), i + t[1 + (e << 1)]
        }, UZIP.F.inflate = function (e, t) {
          var r = Uint8Array;
          if (3 == e[0] && 0 == e[1]) return t || new r(0);
          var i = UZIP.F, o = i._bitsF, a = i._bitsE, s = i._decodeTiny, f = i.makeCodes, l = i.codes2map, c = i._get17, u = i.U, h = null == t;
          h && (t = new r(e.length >>> 2 << 3));
          for (var d, A, g = 0, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0, E = 0, F = 0; 0 == g;) if (g = o(e, F, 1), p = o(e, F + 1, 2), F += 3, 0 != p) {
            if (h && (t = UZIP.F._check(t, E + (1 << 17))), 1 == p && (d = u.flmap, A = u.fdmap, b = 511, y = 31), 2 == p) {
              m = a(e, F, 5) + 257, w = a(e, F + 5, 5) + 1, v = a(e, F + 10, 4) + 4, F += 14;
              for (var _ = 0; _ < 38; _ += 2) u.itree[_] = 0, u.itree[_ + 1] = 0;
              var B = 1;
              for (_ = 0; _ < v; _++) {
                var U = a(e, F + 3 * _, 3);
                u.itree[1 + (u.ordr[_] << 1)] = U, U > B && (B = U)
              }
              F += 3 * v, f(u.itree, B), l(u.itree, B, u.imap), d = u.lmap, A = u.dmap, F = s(u.imap, (1 << B) - 1, m + w, e, F, u.ttree);
              var C = i._copyOut(u.ttree, 0, m, u.ltree);
              b = (1 << C) - 1;
              var I = i._copyOut(u.ttree, m, w, u.dtree);
              y = (1 << I) - 1, f(u.ltree, C), l(u.ltree, C, d), f(u.dtree, I), l(u.dtree, I, A)
            }
            for (; ;) {
              var Q = d[c(e, F) & b];
              F += 15 & Q;
              var M = Q >>> 4;
              if (M >>> 8 == 0) t[E++] = M; else {
                if (256 == M) break;
                var x = E + M - 254;
                if (M > 264) {
                  var T = u.ldef[M - 257];
                  x = E + (T >>> 3) + a(e, F, 7 & T), F += 7 & T
                }
                var S = A[c(e, F) & y];
                F += 15 & S;
                var R = S >>> 4, O = u.ddef[R], P = (O >>> 4) + o(e, F, 15 & O);
                for (F += 15 & O, h && (t = UZIP.F._check(t, E + (1 << 17))); E < x;) t[E] = t[E++ - P], t[E] = t[E++ - P], t[E] = t[E++ - P], t[E] = t[E++ - P];
                E = x
              }
            }
          } else {
            0 != (7 & F) && (F += 8 - (7 & F));
            var H = 4 + (F >>> 3), L = e[H - 4] | e[H - 3] << 8;
            h && (t = UZIP.F._check(t, E + L)), t.set(new r(e.buffer, e.byteOffset + H, L), E), F = H + L << 3, E += L
          }
          return t.length == E ? t : t.slice(0, E)
        }, UZIP.F._check = function (e, t) {
          var r = e.length;
          if (t <= r) return e;
          var i = new Uint8Array(Math.max(r << 1, t));
          return i.set(e, 0), i
        }, UZIP.F._decodeTiny = function (e, t, r, i, o, a) {
          for (var s = UZIP.F._bitsE, f = UZIP.F._get17, l = 0; l < r;) {
            var c = e[f(i, o) & t];
            o += 15 & c;
            var u = c >>> 4;
            if (u <= 15) a[l] = u, l++; else {
              var h = 0, d = 0;
              16 == u ? (d = 3 + s(i, o, 2), o += 2, h = a[l - 1]) : 17 == u ? (d = 3 + s(i, o, 3), o += 3) : 18 == u && (d = 11 + s(i, o, 7), o += 7);
              for (var A = l + d; l < A;) a[l] = h, l++
            }
          }
          return o
        }, UZIP.F._copyOut = function (e, t, r, i) {
          for (var o = 0, a = 0, s = i.length >>> 1; a < r;) {
            var f = e[a + t];
            i[a << 1] = 0, i[1 + (a << 1)] = f, f > o && (o = f), a++
          }
          for (; a < s;) i[a << 1] = 0, i[1 + (a << 1)] = 0, a++;
          return o
        }, UZIP.F.makeCodes = function (e, t) {
          for (var r, i, o, a, s = UZIP.F.U, f = e.length, l = s.bl_count, c = 0; c <= t; c++) l[c] = 0;
          for (c = 1; c < f; c += 2) l[e[c]]++;
          var u = s.next_code;
          for (r = 0, l[0] = 0, i = 1; i <= t; i++) r = r + l[i - 1] << 1, u[i] = r;
          for (o = 0; o < f; o += 2) 0 != (a = e[o + 1]) && (e[o] = u[a], u[a]++)
        }, UZIP.F.codes2map = function (e, t, r) {
          for (var i = e.length, o = UZIP.F.U.rev15, a = 0; a < i; a += 2) if (0 != e[a + 1]) for (var s = a >> 1, f = e[a + 1], l = s << 4 | f, c = t - f, u = e[a] << c, h = u + (1 << c); u != h;) {
            r[o[u] >>> 15 - t] = l, u++
          }
        }, UZIP.F.revCodes = function (e, t) {
          for (var r = UZIP.F.U.rev15, i = 15 - t, o = 0; o < e.length; o += 2) {
            var a = e[o] << t - e[o + 1];
            e[o] = r[a] >>> i
          }
        }, UZIP.F._putsE = function (e, t, r) {
          r <<= 7 & t;
          var i = t >>> 3;
          e[i] |= r, e[i + 1] |= r >>> 8
        }, UZIP.F._putsF = function (e, t, r) {
          r <<= 7 & t;
          var i = t >>> 3;
          e[i] |= r, e[i + 1] |= r >>> 8, e[i + 2] |= r >>> 16
        }, UZIP.F._bitsE = function (e, t, r) {
          return (e[t >>> 3] | e[1 + (t >>> 3)] << 8) >>> (7 & t) & (1 << r) - 1
        }, UZIP.F._bitsF = function (e, t, r) {
          return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) & (1 << r) - 1
        }, UZIP.F._get17 = function (e, t) {
          return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t)
        }, UZIP.F._get25 = function (e, t) {
          return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16 | e[3 + (t >>> 3)] << 24) >>> (7 & t)
        }, UZIP.F.U = (t = Uint16Array, r = Uint32Array, {
          next_code: new t(16),
          bl_count: new t(16),
          ordr: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
          of0: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999],
          exb: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0],
          ldef: new t(32),
          df0: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535],
          dxb: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0],
          ddef: new r(32),
          flmap: new t(512),
          fltree: [],
          fdmap: new t(32),
          fdtree: [],
          lmap: new t(32768),
          ltree: [],
          ttree: [],
          dmap: new t(32768),
          dtree: [],
          imap: new t(512),
          itree: [],
          rev15: new t(32768),
          lhst: new r(286),
          dhst: new r(30),
          ihst: new r(19),
          lits: new r(15e3),
          strt: new t(65536),
          prev: new t(32768)
        }), function () {
          for (var e = UZIP.F.U, t = 0; t < 32768; t++) {
            var r = t;
            r = (4278255360 & (r = (4042322160 & (r = (3435973836 & (r = (2863311530 & r) >>> 1 | (1431655765 & r) << 1)) >>> 2 | (858993459 & r) << 2)) >>> 4 | (252645135 & r) << 4)) >>> 8 | (16711935 & r) << 8, e.rev15[t] = (r >>> 16 | r << 16) >>> 17
          }

          function pushV(e, t, r) {
            for (; 0 != t--;) e.push(0, r)
          }

          for (t = 0; t < 32; t++) e.ldef[t] = e.of0[t] << 3 | e.exb[t], e.ddef[t] = e.df0[t] << 4 | e.dxb[t];
          pushV(e.fltree, 144, 8), pushV(e.fltree, 112, 9), pushV(e.fltree, 24, 7), pushV(e.fltree, 8, 8), UZIP.F.makeCodes(e.fltree, 9), UZIP.F.codes2map(e.fltree, 9, e.flmap), UZIP.F.revCodes(e.fltree, 9), pushV(e.fdtree, 32, 5), UZIP.F.makeCodes(e.fdtree, 5), UZIP.F.codes2map(e.fdtree, 5, e.fdmap), UZIP.F.revCodes(e.fdtree, 5), pushV(e.itree, 19, 0), pushV(e.ltree, 286, 0), pushV(e.dtree, 30, 0), pushV(e.ttree, 320, 0)
        }()
      }({
        get exports() {
          return e
        }, set exports(t) {
          e = t
        }
      });
      var UZIP = _mergeNamespaces({__proto__: null, default: e}, [e]);
      const UPNG = function () {
        var e = {
          nextZero(e, t) {
            for (; 0 != e[t];) t++;
            return t
          }, readUshort: (e, t) => e[t] << 8 | e[t + 1], writeUshort(e, t, r) {
            e[t] = r >> 8 & 255, e[t + 1] = 255 & r
          }, readUint: (e, t) => 16777216 * e[t] + (e[t + 1] << 16 | e[t + 2] << 8 | e[t + 3]), writeUint(e, t, r) {
            e[t] = r >> 24 & 255, e[t + 1] = r >> 16 & 255, e[t + 2] = r >> 8 & 255, e[t + 3] = 255 & r
          }, readASCII(e, t, r) {
            let i = "";
            for (let o = 0; o < r; o++) i += String.fromCharCode(e[t + o]);
            return i
          }, writeASCII(e, t, r) {
            for (let i = 0; i < r.length; i++) e[t + i] = r.charCodeAt(i)
          }, readBytes(e, t, r) {
            const i = [];
            for (let o = 0; o < r; o++) i.push(e[t + o]);
            return i
          }, pad: e => e.length < 2 ? `0${e}` : e, readUTF8(t, r, i) {
            let o, a = "";
            for (let o = 0; o < i; o++) a += `%${e.pad(t[r + o].toString(16))}`;
            try {
              o = decodeURIComponent(a)
            } catch (o) {
              return e.readASCII(t, r, i)
            }
            return o
          }
        };

        function decodeImage(t, r, i, o) {
          const a = r * i, s = _getBPP(o), f = Math.ceil(r * s / 8), l = new Uint8Array(4 * a), c = new Uint32Array(l.buffer), {ctype: u} = o, {depth: h} = o, d = e.readUshort;
          if (6 == u) {
            const e = a << 2;
            if (8 == h) for (var A = 0; A < e; A += 4) l[A] = t[A], l[A + 1] = t[A + 1], l[A + 2] = t[A + 2], l[A + 3] = t[A + 3];
            if (16 == h) for (A = 0; A < e; A++) l[A] = t[A << 1]
          } else if (2 == u) {
            const e = o.tabs.tRNS;
            if (null == e) {
              if (8 == h) for (A = 0; A < a; A++) {
                var g = 3 * A;
                c[A] = 255 << 24 | t[g + 2] << 16 | t[g + 1] << 8 | t[g]
              }
              if (16 == h) for (A = 0; A < a; A++) {
                g = 6 * A;
                c[A] = 255 << 24 | t[g + 4] << 16 | t[g + 2] << 8 | t[g]
              }
            } else {
              var p = e[0];
              const r = e[1], i = e[2];
              if (8 == h) for (A = 0; A < a; A++) {
                var m = A << 2;
                g = 3 * A;
                c[A] = 255 << 24 | t[g + 2] << 16 | t[g + 1] << 8 | t[g], t[g] == p && t[g + 1] == r && t[g + 2] == i && (l[m + 3] = 0)
              }
              if (16 == h) for (A = 0; A < a; A++) {
                m = A << 2, g = 6 * A;
                c[A] = 255 << 24 | t[g + 4] << 16 | t[g + 2] << 8 | t[g], d(t, g) == p && d(t, g + 2) == r && d(t, g + 4) == i && (l[m + 3] = 0)
              }
            }
          } else if (3 == u) {
            const e = o.tabs.PLTE, s = o.tabs.tRNS, c = s ? s.length : 0;
            if (1 == h) for (var w = 0; w < i; w++) {
              var v = w * f, b = w * r;
              for (A = 0; A < r; A++) {
                m = b + A << 2;
                var y = 3 * (E = t[v + (A >> 3)] >> 7 - ((7 & A) << 0) & 1);
                l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255
              }
            }
            if (2 == h) for (w = 0; w < i; w++) for (v = w * f, b = w * r, A = 0; A < r; A++) {
              m = b + A << 2, y = 3 * (E = t[v + (A >> 2)] >> 6 - ((3 & A) << 1) & 3);
              l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255
            }
            if (4 == h) for (w = 0; w < i; w++) for (v = w * f, b = w * r, A = 0; A < r; A++) {
              m = b + A << 2, y = 3 * (E = t[v + (A >> 1)] >> 4 - ((1 & A) << 2) & 15);
              l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255
            }
            if (8 == h) for (A = 0; A < a; A++) {
              var E;
              m = A << 2, y = 3 * (E = t[A]);
              l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255
            }
          } else if (4 == u) {
            if (8 == h) for (A = 0; A < a; A++) {
              m = A << 2;
              var F = t[_ = A << 1];
              l[m] = F, l[m + 1] = F, l[m + 2] = F, l[m + 3] = t[_ + 1]
            }
            if (16 == h) for (A = 0; A < a; A++) {
              var _;
              m = A << 2, F = t[_ = A << 2];
              l[m] = F, l[m + 1] = F, l[m + 2] = F, l[m + 3] = t[_ + 2]
            }
          } else if (0 == u) for (p = o.tabs.tRNS ? o.tabs.tRNS : -1, w = 0; w < i; w++) {
            const e = w * f, i = w * r;
            if (1 == h) for (var B = 0; B < r; B++) {
              var U = (F = 255 * (t[e + (B >>> 3)] >>> 7 - (7 & B) & 1)) == 255 * p ? 0 : 255;
              c[i + B] = U << 24 | F << 16 | F << 8 | F
            } else if (2 == h) for (B = 0; B < r; B++) {
              U = (F = 85 * (t[e + (B >>> 2)] >>> 6 - ((3 & B) << 1) & 3)) == 85 * p ? 0 : 255;
              c[i + B] = U << 24 | F << 16 | F << 8 | F
            } else if (4 == h) for (B = 0; B < r; B++) {
              U = (F = 17 * (t[e + (B >>> 1)] >>> 4 - ((1 & B) << 2) & 15)) == 17 * p ? 0 : 255;
              c[i + B] = U << 24 | F << 16 | F << 8 | F
            } else if (8 == h) for (B = 0; B < r; B++) {
              U = (F = t[e + B]) == p ? 0 : 255;
              c[i + B] = U << 24 | F << 16 | F << 8 | F
            } else if (16 == h) for (B = 0; B < r; B++) {
              F = t[e + (B << 1)], U = d(t, e + (B << 1)) == p ? 0 : 255;
              c[i + B] = U << 24 | F << 16 | F << 8 | F
            }
          }
          return l
        }

        function _decompress(e, r, i, o) {
          const a = _getBPP(e), s = Math.ceil(i * a / 8), f = new Uint8Array((s + 1 + e.interlace) * o);
          return r = e.tabs.CgBI ? t(r, f) : _inflate(r, f), 0 == e.interlace ? r = _filterZero(r, e, 0, i, o) : 1 == e.interlace && (r = function _readInterlace(e, t) {
            const r = t.width, i = t.height, o = _getBPP(t), a = o >> 3, s = Math.ceil(r * o / 8), f = new Uint8Array(i * s);
            let l = 0;
            const c = [0, 0, 4, 0, 2, 0, 1], u = [0, 4, 0, 2, 0, 1, 0], h = [8, 8, 8, 4, 4, 2, 2], d = [8, 8, 4, 4, 2, 2, 1];
            let A = 0;
            for (; A < 7;) {
              const p = h[A], m = d[A];
              let w = 0, v = 0, b = c[A];
              for (; b < i;) b += p, v++;
              let y = u[A];
              for (; y < r;) y += m, w++;
              const E = Math.ceil(w * o / 8);
              _filterZero(e, t, l, w, v);
              let F = 0, _ = c[A];
              for (; _ < i;) {
                let t = u[A], i = l + F * E << 3;
                for (; t < r;) {
                  var g;
                  if (1 == o) g = (g = e[i >> 3]) >> 7 - (7 & i) & 1, f[_ * s + (t >> 3)] |= g << 7 - ((7 & t) << 0);
                  if (2 == o) g = (g = e[i >> 3]) >> 6 - (7 & i) & 3, f[_ * s + (t >> 2)] |= g << 6 - ((3 & t) << 1);
                  if (4 == o) g = (g = e[i >> 3]) >> 4 - (7 & i) & 15, f[_ * s + (t >> 1)] |= g << 4 - ((1 & t) << 2);
                  if (o >= 8) {
                    const r = _ * s + t * a;
                    for (let t = 0; t < a; t++) f[r + t] = e[(i >> 3) + t]
                  }
                  i += o, t += m
                }
                F++, _ += p
              }
              w * v != 0 && (l += v * (1 + E)), A += 1
            }
            return f
          }(r, e)), r
        }

        function _inflate(e, r) {
          return t(new Uint8Array(e.buffer, 2, e.length - 6), r)
        }

        var t = function () {
          const e = {H: {}};
          return e.H.N = function (t, r) {
            const i = Uint8Array;
            let o, a, s = 0, f = 0, l = 0, c = 0, u = 0, h = 0, d = 0, A = 0, g = 0;
            if (3 == t[0] && 0 == t[1]) return r || new i(0);
            const p = e.H, m = p.b, w = p.e, v = p.R, b = p.n, y = p.A, E = p.Z, F = p.m, _ = null == r;
            for (_ && (r = new i(t.length >>> 2 << 5)); 0 == s;) if (s = m(t, g, 1), f = m(t, g + 1, 2), g += 3, 0 != f) {
              if (_ && (r = e.H.W(r, A + (1 << 17))), 1 == f && (o = F.J, a = F.h, h = 511, d = 31), 2 == f) {
                l = w(t, g, 5) + 257, c = w(t, g + 5, 5) + 1, u = w(t, g + 10, 4) + 4, g += 14;
                let e = 1;
                for (var B = 0; B < 38; B += 2) F.Q[B] = 0, F.Q[B + 1] = 0;
                for (B = 0; B < u; B++) {
                  const r = w(t, g + 3 * B, 3);
                  F.Q[1 + (F.X[B] << 1)] = r, r > e && (e = r)
                }
                g += 3 * u, b(F.Q, e), y(F.Q, e, F.u), o = F.w, a = F.d, g = v(F.u, (1 << e) - 1, l + c, t, g, F.v);
                const r = p.V(F.v, 0, l, F.C);
                h = (1 << r) - 1;
                const i = p.V(F.v, l, c, F.D);
                d = (1 << i) - 1, b(F.C, r), y(F.C, r, o), b(F.D, i), y(F.D, i, a)
              }
              for (; ;) {
                const e = o[E(t, g) & h];
                g += 15 & e;
                const i = e >>> 4;
                if (i >>> 8 == 0) r[A++] = i; else {
                  if (256 == i) break;
                  {
                    let e = A + i - 254;
                    if (i > 264) {
                      const r = F.q[i - 257];
                      e = A + (r >>> 3) + w(t, g, 7 & r), g += 7 & r
                    }
                    const o = a[E(t, g) & d];
                    g += 15 & o;
                    const s = o >>> 4, f = F.c[s], l = (f >>> 4) + m(t, g, 15 & f);
                    for (g += 15 & f; A < e;) r[A] = r[A++ - l], r[A] = r[A++ - l], r[A] = r[A++ - l], r[A] = r[A++ - l];
                    A = e
                  }
                }
              }
            } else {
              0 != (7 & g) && (g += 8 - (7 & g));
              const o = 4 + (g >>> 3), a = t[o - 4] | t[o - 3] << 8;
              _ && (r = e.H.W(r, A + a)), r.set(new i(t.buffer, t.byteOffset + o, a), A), g = o + a << 3, A += a
            }
            return r.length == A ? r : r.slice(0, A)
          }, e.H.W = function (e, t) {
            const r = e.length;
            if (t <= r) return e;
            const i = new Uint8Array(r << 1);
            return i.set(e, 0), i
          }, e.H.R = function (t, r, i, o, a, s) {
            const f = e.H.e, l = e.H.Z;
            let c = 0;
            for (; c < i;) {
              const e = t[l(o, a) & r];
              a += 15 & e;
              const i = e >>> 4;
              if (i <= 15) s[c] = i, c++; else {
                let e = 0, t = 0;
                16 == i ? (t = 3 + f(o, a, 2), a += 2, e = s[c - 1]) : 17 == i ? (t = 3 + f(o, a, 3), a += 3) : 18 == i && (t = 11 + f(o, a, 7), a += 7);
                const r = c + t;
                for (; c < r;) s[c] = e, c++
              }
            }
            return a
          }, e.H.V = function (e, t, r, i) {
            let o = 0, a = 0;
            const s = i.length >>> 1;
            for (; a < r;) {
              const r = e[a + t];
              i[a << 1] = 0, i[1 + (a << 1)] = r, r > o && (o = r), a++
            }
            for (; a < s;) i[a << 1] = 0, i[1 + (a << 1)] = 0, a++;
            return o
          }, e.H.n = function (t, r) {
            const i = e.H.m, o = t.length;
            let a, s, f;
            let l;
            const c = i.j;
            for (var u = 0; u <= r; u++) c[u] = 0;
            for (u = 1; u < o; u += 2) c[t[u]]++;
            const h = i.K;
            for (a = 0, c[0] = 0, s = 1; s <= r; s++) a = a + c[s - 1] << 1, h[s] = a;
            for (f = 0; f < o; f += 2) l = t[f + 1], 0 != l && (t[f] = h[l], h[l]++)
          }, e.H.A = function (t, r, i) {
            const o = t.length, a = e.H.m.r;
            for (let e = 0; e < o; e += 2) if (0 != t[e + 1]) {
              const o = e >> 1, s = t[e + 1], f = o << 4 | s, l = r - s;
              let c = t[e] << l;
              const u = c + (1 << l);
              for (; c != u;) {
                i[a[c] >>> 15 - r] = f, c++
              }
            }
          }, e.H.l = function (t, r) {
            const i = e.H.m.r, o = 15 - r;
            for (let e = 0; e < t.length; e += 2) {
              const a = t[e] << r - t[e + 1];
              t[e] = i[a] >>> o
            }
          }, e.H.M = function (e, t, r) {
            r <<= 7 & t;
            const i = t >>> 3;
            e[i] |= r, e[i + 1] |= r >>> 8
          }, e.H.I = function (e, t, r) {
            r <<= 7 & t;
            const i = t >>> 3;
            e[i] |= r, e[i + 1] |= r >>> 8, e[i + 2] |= r >>> 16
          }, e.H.e = function (e, t, r) {
            return (e[t >>> 3] | e[1 + (t >>> 3)] << 8) >>> (7 & t) & (1 << r) - 1
          }, e.H.b = function (e, t, r) {
            return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) & (1 << r) - 1
          }, e.H.Z = function (e, t) {
            return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t)
          }, e.H.i = function (e, t) {
            return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16 | e[3 + (t >>> 3)] << 24) >>> (7 & t)
          }, e.H.m = function () {
            const e = Uint16Array, t = Uint32Array;
            return {
              K: new e(16),
              j: new e(16),
              X: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
              S: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999],
              T: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0],
              q: new e(32),
              p: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535],
              z: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0],
              c: new t(32),
              J: new e(512),
              _: [],
              h: new e(32),
              $: [],
              w: new e(32768),
              C: [],
              v: [],
              d: new e(32768),
              D: [],
              u: new e(512),
              Q: [],
              r: new e(32768),
              s: new t(286),
              Y: new t(30),
              a: new t(19),
              t: new t(15e3),
              k: new e(65536),
              g: new e(32768)
            }
          }(), function () {
            const t = e.H.m;
            for (var r = 0; r < 32768; r++) {
              let e = r;
              e = (2863311530 & e) >>> 1 | (1431655765 & e) << 1, e = (3435973836 & e) >>> 2 | (858993459 & e) << 2, e = (4042322160 & e) >>> 4 | (252645135 & e) << 4, e = (4278255360 & e) >>> 8 | (16711935 & e) << 8, t.r[r] = (e >>> 16 | e << 16) >>> 17
            }

            function n(e, t, r) {
              for (; 0 != t--;) e.push(0, r)
            }

            for (r = 0; r < 32; r++) t.q[r] = t.S[r] << 3 | t.T[r], t.c[r] = t.p[r] << 4 | t.z[r];
            n(t._, 144, 8), n(t._, 112, 9), n(t._, 24, 7), n(t._, 8, 8), e.H.n(t._, 9), e.H.A(t._, 9, t.J), e.H.l(t._, 9), n(t.$, 32, 5), e.H.n(t.$, 5), e.H.A(t.$, 5, t.h), e.H.l(t.$, 5), n(t.Q, 19, 0), n(t.C, 286, 0), n(t.D, 30, 0), n(t.v, 320, 0)
          }(), e.H.N
        }();

        function _getBPP(e) {
          return [1, null, 3, 1, 2, null, 4][e.ctype] * e.depth
        }

        function _filterZero(e, t, r, i, o) {
          let a = _getBPP(t);
          const s = Math.ceil(i * a / 8);
          let f, l;
          a = Math.ceil(a / 8);
          let c = e[r], u = 0;
          if (c > 1 && (e[r] = [0, 0, 1][c - 2]), 3 == c) for (u = a; u < s; u++) e[u + 1] = e[u + 1] + (e[u + 1 - a] >>> 1) & 255;
          for (let t = 0; t < o; t++) if (f = r + t * s, l = f + t + 1, c = e[l - 1], u = 0, 0 == c) for (; u < s; u++) e[f + u] = e[l + u]; else if (1 == c) {
            for (; u < a; u++) e[f + u] = e[l + u];
            for (; u < s; u++) e[f + u] = e[l + u] + e[f + u - a]
          } else if (2 == c) for (; u < s; u++) e[f + u] = e[l + u] + e[f + u - s]; else if (3 == c) {
            for (; u < a; u++) e[f + u] = e[l + u] + (e[f + u - s] >>> 1);
            for (; u < s; u++) e[f + u] = e[l + u] + (e[f + u - s] + e[f + u - a] >>> 1)
          } else {
            for (; u < a; u++) e[f + u] = e[l + u] + _paeth(0, e[f + u - s], 0);
            for (; u < s; u++) e[f + u] = e[l + u] + _paeth(e[f + u - a], e[f + u - s], e[f + u - a - s])
          }
          return e
        }

        function _paeth(e, t, r) {
          const i = e + t - r, o = i - e, a = i - t, s = i - r;
          return o * o <= a * a && o * o <= s * s ? e : a * a <= s * s ? t : r
        }

        function _IHDR(t, r, i) {
          i.width = e.readUint(t, r), r += 4, i.height = e.readUint(t, r), r += 4, i.depth = t[r], r++, i.ctype = t[r], r++, i.compress = t[r], r++, i.filter = t[r], r++, i.interlace = t[r], r++
        }

        function _copyTile(e, t, r, i, o, a, s, f, l) {
          const c = Math.min(t, o), u = Math.min(r, a);
          let h = 0, d = 0;
          for (let r = 0; r < u; r++) for (let a = 0; a < c; a++) if (s >= 0 && f >= 0 ? (h = r * t + a << 2, d = (f + r) * o + s + a << 2) : (h = (-f + r) * t - s + a << 2, d = r * o + a << 2), 0 == l) i[d] = e[h], i[d + 1] = e[h + 1], i[d + 2] = e[h + 2], i[d + 3] = e[h + 3]; else if (1 == l) {
            var A = e[h + 3] * (1 / 255), g = e[h] * A, p = e[h + 1] * A, m = e[h + 2] * A, w = i[d + 3] * (1 / 255), v = i[d] * w, b = i[d + 1] * w, y = i[d + 2] * w;
            const t = 1 - A, r = A + w * t, o = 0 == r ? 0 : 1 / r;
            i[d + 3] = 255 * r, i[d + 0] = (g + v * t) * o, i[d + 1] = (p + b * t) * o, i[d + 2] = (m + y * t) * o
          } else if (2 == l) {
            A = e[h + 3], g = e[h], p = e[h + 1], m = e[h + 2], w = i[d + 3], v = i[d], b = i[d + 1], y = i[d + 2];
            A == w && g == v && p == b && m == y ? (i[d] = 0, i[d + 1] = 0, i[d + 2] = 0, i[d + 3] = 0) : (i[d] = g, i[d + 1] = p, i[d + 2] = m, i[d + 3] = A)
          } else if (3 == l) {
            A = e[h + 3], g = e[h], p = e[h + 1], m = e[h + 2], w = i[d + 3], v = i[d], b = i[d + 1], y = i[d + 2];
            if (A == w && g == v && p == b && m == y) continue;
            if (A < 220 && w > 20) return !1
          }
          return !0
        }

        return {
          decode: function decode(r) {
            const i = new Uint8Array(r);
            let o = 8;
            const a = e, s = a.readUshort, f = a.readUint, l = {tabs: {}, frames: []}, c = new Uint8Array(i.length);
            let u, h = 0, d = 0;
            const A = [137, 80, 78, 71, 13, 10, 26, 10];
            for (var g = 0; g < 8; g++) if (i[g] != A[g]) throw"The input is not a PNG file!";
            for (; o < i.length;) {
              const e = a.readUint(i, o);
              o += 4;
              const r = a.readASCII(i, o, 4);
              if (o += 4, "IHDR" == r) _IHDR(i, o, l); else if ("iCCP" == r) {
                for (var p = o; 0 != i[p];) p++;
                a.readASCII(i, o, p - o), i[p + 1];
                const s = i.slice(p + 2, o + e);
                let f = null;
                try {
                  f = _inflate(s)
                } catch (e) {
                  f = t(s)
                }
                l.tabs[r] = f
              } else if ("CgBI" == r) l.tabs[r] = i.slice(o, o + 4); else if ("IDAT" == r) {
                for (g = 0; g < e; g++) c[h + g] = i[o + g];
                h += e
              } else if ("acTL" == r) l.tabs[r] = {num_frames: f(i, o), num_plays: f(i, o + 4)}, u = new Uint8Array(i.length); else if ("fcTL" == r) {
                if (0 != d) (E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height), d = 0;
                const e = {x: f(i, o + 12), y: f(i, o + 16), width: f(i, o + 4), height: f(i, o + 8)};
                let t = s(i, o + 22);
                t = s(i, o + 20) / (0 == t ? 100 : t);
                const r = {rect: e, delay: Math.round(1e3 * t), dispose: i[o + 24], blend: i[o + 25]};
                l.frames.push(r)
              } else if ("fdAT" == r) {
                for (g = 0; g < e - 4; g++) u[d + g] = i[o + g + 4];
                d += e - 4
              } else if ("pHYs" == r) l.tabs[r] = [a.readUint(i, o), a.readUint(i, o + 4), i[o + 8]]; else if ("cHRM" == r) {
                l.tabs[r] = [];
                for (g = 0; g < 8; g++) l.tabs[r].push(a.readUint(i, o + 4 * g))
              } else if ("tEXt" == r || "zTXt" == r) {
                null == l.tabs[r] && (l.tabs[r] = {});
                var m = a.nextZero(i, o), w = a.readASCII(i, o, m - o), v = o + e - m - 1;
                if ("tEXt" == r) y = a.readASCII(i, m + 1, v); else {
                  var b = _inflate(i.slice(m + 2, m + 2 + v));
                  y = a.readUTF8(b, 0, b.length)
                }
                l.tabs[r][w] = y
              } else if ("iTXt" == r) {
                null == l.tabs[r] && (l.tabs[r] = {});
                m = 0, p = o;
                m = a.nextZero(i, p);
                w = a.readASCII(i, p, m - p);
                const t = i[p = m + 1];
                var y;
                i[p + 1], p += 2, m = a.nextZero(i, p), a.readASCII(i, p, m - p), p = m + 1, m = a.nextZero(i, p), a.readUTF8(i, p, m - p);
                v = e - ((p = m + 1) - o);
                if (0 == t) y = a.readUTF8(i, p, v); else {
                  b = _inflate(i.slice(p, p + v));
                  y = a.readUTF8(b, 0, b.length)
                }
                l.tabs[r][w] = y
              } else if ("PLTE" == r) l.tabs[r] = a.readBytes(i, o, e); else if ("hIST" == r) {
                const e = l.tabs.PLTE.length / 3;
                l.tabs[r] = [];
                for (g = 0; g < e; g++) l.tabs[r].push(s(i, o + 2 * g))
              } else if ("tRNS" == r) 3 == l.ctype ? l.tabs[r] = a.readBytes(i, o, e) : 0 == l.ctype ? l.tabs[r] = s(i, o) : 2 == l.ctype && (l.tabs[r] = [s(i, o), s(i, o + 2), s(i, o + 4)]); else if ("gAMA" == r) l.tabs[r] = a.readUint(i, o) / 1e5; else if ("sRGB" == r) l.tabs[r] = i[o]; else if ("bKGD" == r) 0 == l.ctype || 4 == l.ctype ? l.tabs[r] = [s(i, o)] : 2 == l.ctype || 6 == l.ctype ? l.tabs[r] = [s(i, o), s(i, o + 2), s(i, o + 4)] : 3 == l.ctype && (l.tabs[r] = i[o]); else if ("IEND" == r) break;
              o += e, a.readUint(i, o), o += 4
            }
            var E;
            return 0 != d && ((E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height)), l.data = _decompress(l, c, l.width, l.height), delete l.compress, delete l.interlace, delete l.filter, l
          }, toRGBA8: function toRGBA8(e) {
            const t = e.width, r = e.height;
            if (null == e.tabs.acTL) return [decodeImage(e.data, t, r, e).buffer];
            const i = [];
            null == e.frames[0].data && (e.frames[0].data = e.data);
            const o = t * r * 4, a = new Uint8Array(o), s = new Uint8Array(o), f = new Uint8Array(o);
            for (let c = 0; c < e.frames.length; c++) {
              const u = e.frames[c], h = u.rect.x, d = u.rect.y, A = u.rect.width, g = u.rect.height, p = decodeImage(u.data, A, g, e);
              if (0 != c) for (var l = 0; l < o; l++) f[l] = a[l];
              if (0 == u.blend ? _copyTile(p, A, g, a, t, r, h, d, 0) : 1 == u.blend && _copyTile(p, A, g, a, t, r, h, d, 1), i.push(a.buffer.slice(0)), 0 == u.dispose) ; else if (1 == u.dispose) _copyTile(s, A, g, a, t, r, h, d, 0); else if (2 == u.dispose) for (l = 0; l < o; l++) a[l] = f[l]
            }
            return i
          }, _paeth: _paeth, _copyTile: _copyTile, _bin: e
        }
      }();
      !function () {
        const {_copyTile: e} = UPNG, {_bin: t} = UPNG, r = UPNG._paeth;
        var i = {
          table: function () {
            const e = new Uint32Array(256);
            for (let t = 0; t < 256; t++) {
              let r = t;
              for (let e = 0; e < 8; e++) 1 & r ? r = 3988292384 ^ r >>> 1 : r >>>= 1;
              e[t] = r
            }
            return e
          }(), update(e, t, r, o) {
            for (let a = 0; a < o; a++) e = i.table[255 & (e ^ t[r + a])] ^ e >>> 8;
            return e
          }, crc: (e, t, r) => 4294967295 ^ i.update(4294967295, e, t, r)
        };

        function addErr(e, t, r, i) {
          t[r] += e[0] * i >> 4, t[r + 1] += e[1] * i >> 4, t[r + 2] += e[2] * i >> 4, t[r + 3] += e[3] * i >> 4
        }

        function N(e) {
          return Math.max(0, Math.min(255, e))
        }

        function D(e, t) {
          const r = e[0] - t[0], i = e[1] - t[1], o = e[2] - t[2], a = e[3] - t[3];
          return r * r + i * i + o * o + a * a
        }

        function dither(e, t, r, i, o, a, s) {
          null == s && (s = 1);
          const f = i.length, l = [];
          for (var c = 0; c < f; c++) {
            const e = i[c];
            l.push([e >>> 0 & 255, e >>> 8 & 255, e >>> 16 & 255, e >>> 24 & 255])
          }
          for (c = 0; c < f; c++) {
            let e = 4294967295;
            for (var u = 0, h = 0; h < f; h++) {
              var d = D(l[c], l[h]);
              h != c && d < e && (e = d, u = h)
            }
          }
          const A = new Uint32Array(o.buffer), g = new Int16Array(t * r * 4), p = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
          for (c = 0; c < p.length; c++) p[c] = 255 * ((p[c] + .5) / 16 - .5);
          for (let o = 0; o < r; o++) for (let w = 0; w < t; w++) {
            var m;
            c = 4 * (o * t + w);
            if (2 != s) m = [N(e[c] + g[c]), N(e[c + 1] + g[c + 1]), N(e[c + 2] + g[c + 2]), N(e[c + 3] + g[c + 3])]; else {
              d = p[4 * (3 & o) + (3 & w)];
              m = [N(e[c] + d), N(e[c + 1] + d), N(e[c + 2] + d), N(e[c + 3] + d)]
            }
            u = 0;
            let v = 16777215;
            for (h = 0; h < f; h++) {
              const e = D(m, l[h]);
              e < v && (v = e, u = h)
            }
            const b = l[u], y = [m[0] - b[0], m[1] - b[1], m[2] - b[2], m[3] - b[3]];
            1 == s && (w != t - 1 && addErr(y, g, c + 4, 7), o != r - 1 && (0 != w && addErr(y, g, c + 4 * t - 4, 3), addErr(y, g, c + 4 * t, 5), w != t - 1 && addErr(y, g, c + 4 * t + 4, 1))), a[c >> 2] = u, A[c >> 2] = i[u]
          }
        }

        function _main(e, r, o, a, s) {
          null == s && (s = {});
          const {crc: f} = i, l = t.writeUint, c = t.writeUshort, u = t.writeASCII;
          let h = 8;
          const d = e.frames.length > 1;
          let A, g = !1, p = 33 + (d ? 20 : 0);
          if (null != s.sRGB && (p += 13), null != s.pHYs && (p += 21), null != s.iCCP && (A = pako.deflate(s.iCCP), p += 21 + A.length + 4), 3 == e.ctype) {
            for (var m = e.plte.length, w = 0; w < m; w++) e.plte[w] >>> 24 != 255 && (g = !0);
            p += 8 + 3 * m + 4 + (g ? 8 + 1 * m + 4 : 0)
          }
          for (var v = 0; v < e.frames.length; v++) {
            d && (p += 38), p += (F = e.frames[v]).cimg.length + 12, 0 != v && (p += 4)
          }
          p += 12;
          const b = new Uint8Array(p), y = [137, 80, 78, 71, 13, 10, 26, 10];
          for (w = 0; w < 8; w++) b[w] = y[w];
          if (l(b, h, 13), h += 4, u(b, h, "IHDR"), h += 4, l(b, h, r), h += 4, l(b, h, o), h += 4, b[h] = e.depth, h++, b[h] = e.ctype, h++, b[h] = 0, h++, b[h] = 0, h++, b[h] = 0, h++, l(b, h, f(b, h - 17, 17)), h += 4, null != s.sRGB && (l(b, h, 1), h += 4, u(b, h, "sRGB"), h += 4, b[h] = s.sRGB, h++, l(b, h, f(b, h - 5, 5)), h += 4), null != s.iCCP) {
            const e = 13 + A.length;
            l(b, h, e), h += 4, u(b, h, "iCCP"), h += 4, u(b, h, "ICC profile"), h += 11, h += 2, b.set(A, h), h += A.length, l(b, h, f(b, h - (e + 4), e + 4)), h += 4
          }
          if (null != s.pHYs && (l(b, h, 9), h += 4, u(b, h, "pHYs"), h += 4, l(b, h, s.pHYs[0]), h += 4, l(b, h, s.pHYs[1]), h += 4, b[h] = s.pHYs[2], h++, l(b, h, f(b, h - 13, 13)), h += 4), d && (l(b, h, 8), h += 4, u(b, h, "acTL"), h += 4, l(b, h, e.frames.length), h += 4, l(b, h, null != s.loop ? s.loop : 0), h += 4, l(b, h, f(b, h - 12, 12)), h += 4), 3 == e.ctype) {
            l(b, h, 3 * (m = e.plte.length)), h += 4, u(b, h, "PLTE"), h += 4;
            for (w = 0; w < m; w++) {
              const t = 3 * w, r = e.plte[w], i = 255 & r, o = r >>> 8 & 255, a = r >>> 16 & 255;
              b[h + t + 0] = i, b[h + t + 1] = o, b[h + t + 2] = a
            }
            if (h += 3 * m, l(b, h, f(b, h - 3 * m - 4, 3 * m + 4)), h += 4, g) {
              l(b, h, m), h += 4, u(b, h, "tRNS"), h += 4;
              for (w = 0; w < m; w++) b[h + w] = e.plte[w] >>> 24 & 255;
              h += m, l(b, h, f(b, h - m - 4, m + 4)), h += 4
            }
          }
          let E = 0;
          for (v = 0; v < e.frames.length; v++) {
            var F = e.frames[v];
            d && (l(b, h, 26), h += 4, u(b, h, "fcTL"), h += 4, l(b, h, E++), h += 4, l(b, h, F.rect.width), h += 4, l(b, h, F.rect.height), h += 4, l(b, h, F.rect.x), h += 4, l(b, h, F.rect.y), h += 4, c(b, h, a[v]), h += 2, c(b, h, 1e3), h += 2, b[h] = F.dispose, h++, b[h] = F.blend, h++, l(b, h, f(b, h - 30, 30)), h += 4);
            const t = F.cimg;
            l(b, h, (m = t.length) + (0 == v ? 0 : 4)), h += 4;
            const r = h;
            u(b, h, 0 == v ? "IDAT" : "fdAT"), h += 4, 0 != v && (l(b, h, E++), h += 4), b.set(t, h), h += m, l(b, h, f(b, r, h - r)), h += 4
          }
          return l(b, h, 0), h += 4, u(b, h, "IEND"), h += 4, l(b, h, f(b, h - 4, 4)), h += 4, b.buffer
        }

        function compressPNG(e, t, r) {
          for (let i = 0; i < e.frames.length; i++) {
            const o = e.frames[i];
            o.rect.width;
            const a = o.rect.height, s = new Uint8Array(a * o.bpl + a);
            o.cimg = _filterZero(o.img, a, o.bpp, o.bpl, s, t, r)
          }
        }

        function compress(t, r, i, o, a) {
          const s = a[0], f = a[1], l = a[2], c = a[3], u = a[4], h = a[5];
          let d = 6, A = 8, g = 255;
          for (var p = 0; p < t.length; p++) {
            const e = new Uint8Array(t[p]);
            for (var m = e.length, w = 0; w < m; w += 4) g &= e[w + 3]
          }
          const v = 255 != g, b = function framize(t, r, i, o, a, s) {
            const f = [];
            for (var l = 0; l < t.length; l++) {
              const h = new Uint8Array(t[l]), A = new Uint32Array(h.buffer);
              var c;
              let g = 0, p = 0, m = r, w = i, v = o ? 1 : 0;
              if (0 != l) {
                const b = s || o || 1 == l || 0 != f[l - 2].dispose ? 1 : 2;
                let y = 0, E = 1e9;
                for (let e = 0; e < b; e++) {
                  var u = new Uint8Array(t[l - 1 - e]);
                  const o = new Uint32Array(t[l - 1 - e]);
                  let s = r, f = i, c = -1, h = -1;
                  for (let e = 0; e < i; e++) for (let t = 0; t < r; t++) {
                    A[d = e * r + t] != o[d] && (t < s && (s = t), t > c && (c = t), e < f && (f = e), e > h && (h = e))
                  }
                  -1 == c && (s = f = c = h = 0), a && (1 == (1 & s) && s--, 1 == (1 & f) && f--);
                  const v = (c - s + 1) * (h - f + 1);
                  v < E && (E = v, y = e, g = s, p = f, m = c - s + 1, w = h - f + 1)
                }
                u = new Uint8Array(t[l - 1 - y]);
                1 == y && (f[l - 1].dispose = 2), c = new Uint8Array(m * w * 4), e(u, r, i, c, m, w, -g, -p, 0), v = e(h, r, i, c, m, w, -g, -p, 3) ? 1 : 0, 1 == v ? _prepareDiff(h, r, i, c, {
                  x: g,
                  y: p,
                  width: m,
                  height: w
                }) : e(h, r, i, c, m, w, -g, -p, 0)
              } else c = h.slice(0);
              f.push({rect: {x: g, y: p, width: m, height: w}, img: c, blend: v, dispose: 0})
            }
            if (o) for (l = 0; l < f.length; l++) {
              if (1 == (A = f[l]).blend) continue;
              const e = A.rect, o = f[l - 1].rect, s = Math.min(e.x, o.x), c = Math.min(e.y, o.y), u = {x: s, y: c, width: Math.max(e.x + e.width, o.x + o.width) - s, height: Math.max(e.y + e.height, o.y + o.height) - c};
              f[l - 1].dispose = 1, l - 1 != 0 && _updateFrame(t, r, i, f, l - 1, u, a), _updateFrame(t, r, i, f, l, u, a)
            }
            let h = 0;
            if (1 != t.length) for (var d = 0; d < f.length; d++) {
              var A;
              h += (A = f[d]).rect.width * A.rect.height
            }
            return f
          }(t, r, i, s, f, l), y = {}, E = [], F = [];
          if (0 != o) {
            const e = [];
            for (w = 0; w < b.length; w++) e.push(b[w].img.buffer);
            const t = function concatRGBA(e) {
              let t = 0;
              for (var r = 0; r < e.length; r++) t += e[r].byteLength;
              const i = new Uint8Array(t);
              let o = 0;
              for (r = 0; r < e.length; r++) {
                const t = new Uint8Array(e[r]), a = t.length;
                for (let e = 0; e < a; e += 4) {
                  let r = t[e], a = t[e + 1], s = t[e + 2];
                  const f = t[e + 3];
                  0 == f && (r = a = s = 0), i[o + e] = r, i[o + e + 1] = a, i[o + e + 2] = s, i[o + e + 3] = f
                }
                o += a
              }
              return i.buffer
            }(e), r = quantize(t, o);
            for (w = 0; w < r.plte.length; w++) E.push(r.plte[w].est.rgba);
            let i = 0;
            for (w = 0; w < b.length; w++) {
              const e = (B = b[w]).img.length;
              var _ = new Uint8Array(r.inds.buffer, i >> 2, e >> 2);
              F.push(_);
              const t = new Uint8Array(r.abuf, i, e);
              h && dither(B.img, B.rect.width, B.rect.height, E, t, _), B.img.set(t), i += e
            }
          } else for (p = 0; p < b.length; p++) {
            var B = b[p];
            const e = new Uint32Array(B.img.buffer);
            var U = B.rect.width;
            m = e.length, _ = new Uint8Array(m);
            F.push(_);
            for (w = 0; w < m; w++) {
              const t = e[w];
              if (0 != w && t == e[w - 1]) _[w] = _[w - 1]; else if (w > U && t == e[w - U]) _[w] = _[w - U]; else {
                let e = y[t];
                if (null == e && (y[t] = e = E.length, E.push(t), E.length >= 300)) break;
                _[w] = e
              }
            }
          }
          const C = E.length;
          C <= 256 && 0 == u && (A = C <= 2 ? 1 : C <= 4 ? 2 : C <= 16 ? 4 : 8, A = Math.max(A, c));
          for (p = 0; p < b.length; p++) {
            (B = b[p]).rect.x, B.rect.y;
            U = B.rect.width;
            const e = B.rect.height;
            let t = B.img;
            new Uint32Array(t.buffer);
            let r = 4 * U, i = 4;
            if (C <= 256 && 0 == u) {
              r = Math.ceil(A * U / 8);
              var I = new Uint8Array(r * e);
              const o = F[p];
              for (let t = 0; t < e; t++) {
                w = t * r;
                const e = t * U;
                if (8 == A) for (var Q = 0; Q < U; Q++) I[w + Q] = o[e + Q]; else if (4 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 1)] |= o[e + Q] << 4 - 4 * (1 & Q); else if (2 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 2)] |= o[e + Q] << 6 - 2 * (3 & Q); else if (1 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 3)] |= o[e + Q] << 7 - 1 * (7 & Q)
              }
              t = I, d = 3, i = 1
            } else if (0 == v && 1 == b.length) {
              I = new Uint8Array(U * e * 3);
              const o = U * e;
              for (w = 0; w < o; w++) {
                const e = 3 * w, r = 4 * w;
                I[e] = t[r], I[e + 1] = t[r + 1], I[e + 2] = t[r + 2]
              }
              t = I, d = 2, i = 3, r = 3 * U
            }
            B.img = t, B.bpl = r, B.bpp = i
          }
          return {ctype: d, depth: A, plte: E, frames: b}
        }

        function _updateFrame(t, r, i, o, a, s, f) {
          const l = Uint8Array, c = Uint32Array, u = new l(t[a - 1]), h = new c(t[a - 1]), d = a + 1 < t.length ? new l(t[a + 1]) : null, A = new l(t[a]), g = new c(A.buffer);
          let p = r, m = i, w = -1, v = -1;
          for (let e = 0; e < s.height; e++) for (let t = 0; t < s.width; t++) {
            const i = s.x + t, f = s.y + e, l = f * r + i, c = g[l];
            0 == c || 0 == o[a - 1].dispose && h[l] == c && (null == d || 0 != d[4 * l + 3]) || (i < p && (p = i), i > w && (w = i), f < m && (m = f), f > v && (v = f))
          }
          -1 == w && (p = m = w = v = 0), f && (1 == (1 & p) && p--, 1 == (1 & m) && m--), s = {x: p, y: m, width: w - p + 1, height: v - m + 1};
          const b = o[a];
          b.rect = s, b.blend = 1, b.img = new Uint8Array(s.width * s.height * 4), 0 == o[a - 1].dispose ? (e(u, r, i, b.img, s.width, s.height, -s.x, -s.y, 0), _prepareDiff(A, r, i, b.img, s)) : e(A, r, i, b.img, s.width, s.height, -s.x, -s.y, 0)
        }

        function _prepareDiff(t, r, i, o, a) {
          e(t, r, i, o, a.width, a.height, -a.x, -a.y, 2)
        }

        function _filterZero(e, t, r, i, o, a, s) {
          const f = [];
          let l, c = [0, 1, 2, 3, 4];
          -1 != a ? c = [a] : (t * i > 5e5 || 1 == r) && (c = [0]), s && (l = {level: 0});
          const u = UZIP;
          for (var h = 0; h < c.length; h++) {
            for (let a = 0; a < t; a++) _filterLine(o, e, a, i, r, c[h]);
            f.push(u.deflate(o, l))
          }
          let d, A = 1e9;
          for (h = 0; h < f.length; h++) f[h].length < A && (d = h, A = f[h].length);
          return f[d]
        }

        function _filterLine(e, t, i, o, a, s) {
          const f = i * o;
          let l = f + i;
          if (e[l] = s, l++, 0 == s) if (o < 500) for (var c = 0; c < o; c++) e[l + c] = t[f + c]; else e.set(new Uint8Array(t.buffer, f, o), l); else if (1 == s) {
            for (c = 0; c < a; c++) e[l + c] = t[f + c];
            for (c = a; c < o; c++) e[l + c] = t[f + c] - t[f + c - a] + 256 & 255
          } else if (0 == i) {
            for (c = 0; c < a; c++) e[l + c] = t[f + c];
            if (2 == s) for (c = a; c < o; c++) e[l + c] = t[f + c];
            if (3 == s) for (c = a; c < o; c++) e[l + c] = t[f + c] - (t[f + c - a] >> 1) + 256 & 255;
            if (4 == s) for (c = a; c < o; c++) e[l + c] = t[f + c] - r(t[f + c - a], 0, 0) + 256 & 255
          } else {
            if (2 == s) for (c = 0; c < o; c++) e[l + c] = t[f + c] + 256 - t[f + c - o] & 255;
            if (3 == s) {
              for (c = 0; c < a; c++) e[l + c] = t[f + c] + 256 - (t[f + c - o] >> 1) & 255;
              for (c = a; c < o; c++) e[l + c] = t[f + c] + 256 - (t[f + c - o] + t[f + c - a] >> 1) & 255
            }
            if (4 == s) {
              for (c = 0; c < a; c++) e[l + c] = t[f + c] + 256 - r(0, t[f + c - o], 0) & 255;
              for (c = a; c < o; c++) e[l + c] = t[f + c] + 256 - r(t[f + c - a], t[f + c - o], t[f + c - a - o]) & 255
            }
          }
        }

        function quantize(e, t) {
          const r = new Uint8Array(e), i = r.slice(0), o = new Uint32Array(i.buffer), a = getKDtree(i, t), s = a[0], f = a[1], l = r.length, c = new Uint8Array(l >> 2);
          let u;
          if (r.length < 2e7) for (var h = 0; h < l; h += 4) {
            u = getNearest(s, d = r[h] * (1 / 255), A = r[h + 1] * (1 / 255), g = r[h + 2] * (1 / 255), p = r[h + 3] * (1 / 255)), c[h >> 2] = u.ind, o[h >> 2] = u.est.rgba
          } else for (h = 0; h < l; h += 4) {
            var d = r[h] * (1 / 255), A = r[h + 1] * (1 / 255), g = r[h + 2] * (1 / 255), p = r[h + 3] * (1 / 255);
            for (u = s; u.left;) u = planeDst(u.est, d, A, g, p) <= 0 ? u.left : u.right;
            c[h >> 2] = u.ind, o[h >> 2] = u.est.rgba
          }
          return {abuf: i.buffer, inds: c, plte: f}
        }

        function getKDtree(e, t, r) {
          null == r && (r = 1e-4);
          const i = new Uint32Array(e.buffer), o = {i0: 0, i1: e.length, bst: null, est: null, tdst: 0, left: null, right: null};
          o.bst = stats(e, o.i0, o.i1), o.est = estats(o.bst);
          const a = [o];
          for (; a.length < t;) {
            let t = 0, o = 0;
            for (var s = 0; s < a.length; s++) a[s].est.L > t && (t = a[s].est.L, o = s);
            if (t < r) break;
            const f = a[o], l = splitPixels(e, i, f.i0, f.i1, f.est.e, f.est.eMq255);
            if (f.i0 >= l || f.i1 <= l) {
              f.est.L = 0;
              continue
            }
            const c = {i0: f.i0, i1: l, bst: null, est: null, tdst: 0, left: null, right: null};
            c.bst = stats(e, c.i0, c.i1), c.est = estats(c.bst);
            const u = {i0: l, i1: f.i1, bst: null, est: null, tdst: 0, left: null, right: null};
            u.bst = {R: [], m: [], N: f.bst.N - c.bst.N};
            for (s = 0; s < 16; s++) u.bst.R[s] = f.bst.R[s] - c.bst.R[s];
            for (s = 0; s < 4; s++) u.bst.m[s] = f.bst.m[s] - c.bst.m[s];
            u.est = estats(u.bst), f.left = c, f.right = u, a[o] = c, a.push(u)
          }
          a.sort((e, t) => t.bst.N - e.bst.N);
          for (s = 0; s < a.length; s++) a[s].ind = s;
          return [o, a]
        }

        function getNearest(e, t, r, i, o) {
          if (null == e.left) return e.tdst = function dist(e, t, r, i, o) {
            const a = t - e[0], s = r - e[1], f = i - e[2], l = o - e[3];
            return a * a + s * s + f * f + l * l
          }(e.est.q, t, r, i, o), e;
          const a = planeDst(e.est, t, r, i, o);
          let s = e.left, f = e.right;
          a > 0 && (s = e.right, f = e.left);
          const l = getNearest(s, t, r, i, o);
          if (l.tdst <= a * a) return l;
          const c = getNearest(f, t, r, i, o);
          return c.tdst < l.tdst ? c : l
        }

        function planeDst(e, t, r, i, o) {
          const {e: a} = e;
          return a[0] * t + a[1] * r + a[2] * i + a[3] * o - e.eMq
        }

        function splitPixels(e, t, r, i, o, a) {
          for (i -= 4; r < i;) {
            for (; vecDot(e, r, o) <= a;) r += 4;
            for (; vecDot(e, i, o) > a;) i -= 4;
            if (r >= i) break;
            const s = t[r >> 2];
            t[r >> 2] = t[i >> 2], t[i >> 2] = s, r += 4, i -= 4
          }
          for (; vecDot(e, r, o) > a;) r -= 4;
          return r + 4
        }

        function vecDot(e, t, r) {
          return e[t] * r[0] + e[t + 1] * r[1] + e[t + 2] * r[2] + e[t + 3] * r[3]
        }

        function stats(e, t, r) {
          const i = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], o = [0, 0, 0, 0], a = r - t >> 2;
          for (let a = t; a < r; a += 4) {
            const t = e[a] * (1 / 255), r = e[a + 1] * (1 / 255), s = e[a + 2] * (1 / 255), f = e[a + 3] * (1 / 255);
            o[0] += t, o[1] += r, o[2] += s, o[3] += f, i[0] += t * t, i[1] += t * r, i[2] += t * s, i[3] += t * f, i[5] += r * r, i[6] += r * s, i[7] += r * f, i[10] += s * s, i[11] += s * f, i[15] += f * f
          }
          return i[4] = i[1], i[8] = i[2], i[9] = i[6], i[12] = i[3], i[13] = i[7], i[14] = i[11], {R: i, m: o, N: a}
        }

        function estats(e) {
          const {R: t} = e, {m: r} = e, {N: i} = e, a = r[0], s = r[1], f = r[2], l = r[3], c = 0 == i ? 0 : 1 / i,
            u = [t[0] - a * a * c, t[1] - a * s * c, t[2] - a * f * c, t[3] - a * l * c, t[4] - s * a * c, t[5] - s * s * c, t[6] - s * f * c, t[7] - s * l * c, t[8] - f * a * c, t[9] - f * s * c, t[10] - f * f * c, t[11] - f * l * c, t[12] - l * a * c, t[13] - l * s * c, t[14] - l * f * c, t[15] - l * l * c],
            h = u, d = o;
          let A = [Math.random(), Math.random(), Math.random(), Math.random()], g = 0, p = 0;
          if (0 != i) for (let e = 0; e < 16 && (A = d.multVec(h, A), p = Math.sqrt(d.dot(A, A)), A = d.sml(1 / p, A), !(0 != e && Math.abs(p - g) < 1e-9)); e++) g = p;
          const m = [a * c, s * c, f * c, l * c];
          return {Cov: u, q: m, e: A, L: g, eMq255: d.dot(d.sml(255, m), A), eMq: d.dot(A, m), rgba: (Math.round(255 * m[3]) << 24 | Math.round(255 * m[2]) << 16 | Math.round(255 * m[1]) << 8 | Math.round(255 * m[0]) << 0) >>> 0}
        }

        var o = {
          multVec: (e, t) => [e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3], e[4] * t[0] + e[5] * t[1] + e[6] * t[2] + e[7] * t[3], e[8] * t[0] + e[9] * t[1] + e[10] * t[2] + e[11] * t[3], e[12] * t[0] + e[13] * t[1] + e[14] * t[2] + e[15] * t[3]],
          dot: (e, t) => e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3],
          sml: (e, t) => [e * t[0], e * t[1], e * t[2], e * t[3]]
        };
        UPNG.encode = function encode(e, t, r, i, o, a, s) {
          null == i && (i = 0), null == s && (s = !1);
          const f = compress(e, t, r, i, [!1, !1, !1, 0, s, !1]);
          return compressPNG(f, -1), _main(f, t, r, o, a)
        }, UPNG.encodeLL = function encodeLL(e, t, r, i, o, a, s, f) {
          const l = {ctype: 0 + (1 == i ? 0 : 2) + (0 == o ? 0 : 4), depth: a, frames: []}, c = (i + o) * a, u = c * t;
          for (let i = 0; i < e.length; i++) l.frames.push({rect: {x: 0, y: 0, width: t, height: r}, img: new Uint8Array(e[i]), blend: 0, dispose: 1, bpp: Math.ceil(c / 8), bpl: Math.ceil(u / 8)});
          return compressPNG(l, 0, !0), _main(l, t, r, s, f)
        }, UPNG.encode.compress = compress, UPNG.encode.dither = dither, UPNG.quantize = quantize, UPNG.quantize.getKDtree = getKDtree, UPNG.quantize.getNearest = getNearest
      }();
      const t = {
        toArrayBuffer(e, r) {
          const i = e.width, o = e.height, a = i << 2, s = e.getContext("2d").getImageData(0, 0, i, o), f = new Uint32Array(s.data.buffer), l = (32 * i + 31) / 32 << 2, c = l * o, u = 122 + c, h = new ArrayBuffer(u), d = new DataView(h), A = 1 << 20;
          let g, p, m, w, v = A, b = 0, y = 0, E = 0;

          function set16(e) {
            d.setUint16(y, e, !0), y += 2
          }

          function set32(e) {
            d.setUint32(y, e, !0), y += 4
          }

          function seek(e) {
            y += e
          }

          set16(19778), set32(u), seek(4), set32(122), set32(108), set32(i), set32(-o >>> 0), set16(1), set16(32), set32(3), set32(c), set32(2835), set32(2835), seek(8), set32(16711680), set32(65280), set32(255), set32(4278190080), set32(1466527264), function convert() {
            for (; b < o && v > 0;) {
              for (w = 122 + b * l, g = 0; g < a;) v--, p = f[E++], m = p >>> 24, d.setUint32(w + g, p << 8 | m), g += 4;
              b++
            }
            E < f.length ? (v = A, setTimeout(convert, t._dly)) : r(h)
          }()
        }, toBlob(e, t) {
          this.toArrayBuffer(e, e => {
            t(new Blob([e], {type: "image/bmp"}))
          })
        }, _dly: 9
      };
      var r = {CHROME: "CHROME", FIREFOX: "FIREFOX", DESKTOP_SAFARI: "DESKTOP_SAFARI", IE: "IE", IOS: "IOS", ETC: "ETC"}, i = {[r.CHROME]: 16384, [r.FIREFOX]: 11180, [r.DESKTOP_SAFARI]: 16384, [r.IE]: 8192, [r.IOS]: 4096, [r.ETC]: 8192};
      const o = "undefined" != typeof window, a = "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope, s = o && window.cordova && window.cordova.require && window.cordova.require("cordova/modulemapper"),
        CustomFile = (o || a) && (s && s.getOriginalSymbol(window, "File") || "undefined" != typeof File && File), CustomFileReader = (o || a) && (s && s.getOriginalSymbol(window, "FileReader") || "undefined" != typeof FileReader && FileReader);

      function getFilefromDataUrl(e, t, r = Date.now()) {
        return new Promise(i => {
          const o = e.split(","), a = o[0].match(/:(.*?);/)[1], s = globalThis.atob(o[1]);
          let f = s.length;
          const l = new Uint8Array(f);
          for (; f--;) l[f] = s.charCodeAt(f);
          const c = new Blob([l], {type: a});
          c.name = t, c.lastModified = r, i(c)
        })
      }

      function getDataUrlFromFile(e) {
        return new Promise((t, r) => {
          const i = new CustomFileReader;
          i.onload = () => t(i.result), i.onerror = e => r(e), i.readAsDataURL(e)
        })
      }

      function loadImage(e) {
        return new Promise((t, r) => {
          const i = new Image;
          i.onload = () => t(i), i.onerror = e => r(e), i.src = e
        })
      }

      function getBrowserName() {
        if (void 0 !== getBrowserName.cachedResult) return getBrowserName.cachedResult;
        let e = r.ETC;
        const {userAgent: t} = navigator;
        return /Chrom(e|ium)/i.test(t) ? e = r.CHROME : /iP(ad|od|hone)/i.test(t) && /WebKit/i.test(t) ? e = r.IOS : /Safari/i.test(t) ? e = r.DESKTOP_SAFARI : /Firefox/i.test(t) ? e = r.FIREFOX : (/MSIE/i.test(t) || !0 == !!document.documentMode) && (e = r.IE), getBrowserName.cachedResult = e, getBrowserName.cachedResult
      }

      function approximateBelowMaximumCanvasSizeOfBrowser(e, t) {
        const r = getBrowserName(), o = i[r];
        let a = e, s = t, f = a * s;
        const l = a > s ? s / a : a / s;
        for (; f > o * o;) {
          const e = (o + a) / 2, t = (o + s) / 2;
          e < t ? (s = t, a = t * l) : (s = e * l, a = e), f = a * s
        }
        return {width: a, height: s}
      }

      function getNewCanvasAndCtx(e, t) {
        let r, i;
        try {
          if (r = new OffscreenCanvas(e, t), i = r.getContext("2d"), null === i) throw new Error("getContext of OffscreenCanvas returns null")
        } catch (e) {
          r = document.createElement("canvas"), i = r.getContext("2d")
        }
        return r.width = e, r.height = t, [r, i]
      }

      function drawImageInCanvas(e, t) {
        const {width: r, height: i} = approximateBelowMaximumCanvasSizeOfBrowser(e.width, e.height), [o, a] = getNewCanvasAndCtx(r, i);
        return t && /jpe?g/.test(t) && (a.fillStyle = "white", a.fillRect(0, 0, o.width, o.height)), a.drawImage(e, 0, 0, o.width, o.height), o
      }

      function isIOS() {
        return void 0 !== isIOS.cachedResult || (isIOS.cachedResult = ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "undefined" != typeof document && "ontouchend" in document), isIOS.cachedResult
      }

      function drawFileInCanvas(e, t = {}) {
        return new Promise(function (i, o) {
          let a, s;
          var $Try_2_Post = function () {
            try {
              return s = drawImageInCanvas(a, t.fileType || e.type), i([a, s])
            } catch (e) {
              return o(e)
            }
          }, $Try_2_Catch = function (t) {
            try {
              0;
              var $Try_3_Catch = function (e) {
                try {
                  throw e
                } catch (e) {
                  return o(e)
                }
              };
              try {
                let t;
                return getDataUrlFromFile(e).then(function (e) {
                  try {
                    return t = e, loadImage(t).then(function (e) {
                      try {
                        return a = e, function () {
                          try {
                            return $Try_2_Post()
                          } catch (e) {
                            return o(e)
                          }
                        }()
                      } catch (e) {
                        return $Try_3_Catch(e)
                      }
                    }, $Try_3_Catch)
                  } catch (e) {
                    return $Try_3_Catch(e)
                  }
                }, $Try_3_Catch)
              } catch (e) {
                $Try_3_Catch(e)
              }
            } catch (e) {
              return o(e)
            }
          };
          try {
            if (isIOS() || [r.DESKTOP_SAFARI, r.MOBILE_SAFARI].includes(getBrowserName())) throw new Error("Skip createImageBitmap on IOS and Safari");
            return createImageBitmap(e).then(function (e) {
              try {
                return a = e, $Try_2_Post()
              } catch (e) {
                return $Try_2_Catch()
              }
            }, $Try_2_Catch)
          } catch (e) {
            $Try_2_Catch()
          }
        })
      }

      function canvasToFile(e, r, i, o, a = 1) {
        return new Promise(function (s, f) {
          let l;
          if ("image/png" === r) {
            let c, u, h;
            return c = e.getContext("2d"), {data: u} = c.getImageData(0, 0, e.width, e.height), h = UPNG.encode([u.buffer], e.width, e.height, 4096 * a), l = new Blob([h], {type: r}), l.name = i, l.lastModified = o, $If_4.call(this)
          }
          {
            if ("image/bmp" === r) return new Promise(r => t.toBlob(e, r)).then(function (e) {
              try {
                return l = e, l.name = i, l.lastModified = o, $If_5.call(this)
              } catch (e) {
                return f(e)
              }
            }.bind(this), f);
            {
              if ("function" == typeof OffscreenCanvas && e instanceof OffscreenCanvas) return e.convertToBlob({type: r, quality: a}).then(function (e) {
                try {
                  return l = e, l.name = i, l.lastModified = o, $If_6.call(this)
                } catch (e) {
                  return f(e)
                }
              }.bind(this), f);
              {
                let d;
                return d = e.toDataURL(r, a), getFilefromDataUrl(d, i, o).then(function (e) {
                  try {
                    return l = e, $If_6.call(this)
                  } catch (e) {
                    return f(e)
                  }
                }.bind(this), f)
              }

              function $If_6() {
                return $If_5.call(this)
              }
            }

            function $If_5() {
              return $If_4.call(this)
            }
          }

          function $If_4() {
            return s(l)
          }
        })
      }

      function cleanupCanvasMemory(e) {
        e.width = 0, e.height = 0
      }

      function isAutoOrientationInBrowser() {
        return new Promise(function (e, t) {
          let r, i, o, a, s;
          return void 0 !== isAutoOrientationInBrowser.cachedResult ? e(isAutoOrientationInBrowser.cachedResult) : (r = "", getFilefromDataUrl("", "test.jpg", Date.now()).then(function (r) {
            try {
              return i = r, drawFileInCanvas(i).then(function (r) {
                try {
                  return o = r[1], canvasToFile(o, i.type, i.name, i.lastModified).then(function (r) {
                    try {
                      return a = r, cleanupCanvasMemory(o), drawFileInCanvas(a).then(function (r) {
                        try {
                          return s = r[0], isAutoOrientationInBrowser.cachedResult = 1 === s.width && 2 === s.height, e(isAutoOrientationInBrowser.cachedResult)
                        } catch (e) {
                          return t(e)
                        }
                      }, t)
                    } catch (e) {
                      return t(e)
                    }
                  }, t)
                } catch (e) {
                  return t(e)
                }
              }, t)
            } catch (e) {
              return t(e)
            }
          }, t))
        })
      }

      function getExifOrientation(e) {
        return new Promise((t, r) => {
          const i = new CustomFileReader;
          i.onload = e => {
            const r = new DataView(e.target.result);
            if (65496 != r.getUint16(0, !1)) return t(-2);
            const i = r.byteLength;
            let o = 2;
            for (; o < i;) {
              if (r.getUint16(o + 2, !1) <= 8) return t(-1);
              const e = r.getUint16(o, !1);
              if (o += 2, 65505 == e) {
                if (1165519206 != r.getUint32(o += 2, !1)) return t(-1);
                const e = 18761 == r.getUint16(o += 6, !1);
                o += r.getUint32(o + 4, e);
                const i = r.getUint16(o, e);
                o += 2;
                for (let a = 0; a < i; a++) if (274 == r.getUint16(o + 12 * a, e)) return t(r.getUint16(o + 12 * a + 8, e))
              } else {
                if (65280 != (65280 & e)) break;
                o += r.getUint16(o, !1)
              }
            }
            return t(-1)
          }, i.onerror = e => r(e), i.readAsArrayBuffer(e)
        })
      }

      function handleMaxWidthOrHeight(e, t) {
        const {width: r} = e, {height: i} = e, {maxWidthOrHeight: o} = t;
        let a, s = e;
        return isFinite(o) && (r > o || i > o) && ([s, a] = getNewCanvasAndCtx(r, i), r > i ? (s.width = o, s.height = i / r * o) : (s.width = r / i * o, s.height = o), a.drawImage(e, 0, 0, s.width, s.height), cleanupCanvasMemory(e)), s
      }

      function followExifOrientation(e, t) {
        const {width: r} = e, {height: i} = e, [o, a] = getNewCanvasAndCtx(r, i);
        switch (t > 4 && t < 9 ? (o.width = i, o.height = r) : (o.width = r, o.height = i), t) {
          case 2:
            a.transform(-1, 0, 0, 1, r, 0);
            break;
          case 3:
            a.transform(-1, 0, 0, -1, r, i);
            break;
          case 4:
            a.transform(1, 0, 0, -1, 0, i);
            break;
          case 5:
            a.transform(0, 1, 1, 0, 0, 0);
            break;
          case 6:
            a.transform(0, 1, -1, 0, i, 0);
            break;
          case 7:
            a.transform(0, -1, -1, 0, i, r);
            break;
          case 8:
            a.transform(0, -1, 1, 0, 0, r)
        }
        return a.drawImage(e, 0, 0, r, i), cleanupCanvasMemory(e), o
      }

      function compress(e, t, r = 0) {
        return new Promise(function (i, o) {
          let a, s, f, l, c, u, h, d, A, g, p, m, w, v, b, y, E, F, _, B;

          function incProgress(e = 5) {
            if (t.signal && t.signal.aborted) throw t.signal.reason;
            a += e, t.onProgress(Math.min(a, 100))
          }

          function setProgress(e) {
            if (t.signal && t.signal.aborted) throw t.signal.reason;
            a = Math.min(Math.max(e, a), 100), t.onProgress(a)
          }

          return a = r, s = t.maxIteration || 10, f = 1024 * t.maxSizeMB * 1024, incProgress(), drawFileInCanvas(e, t).then(function (r) {
            try {
              return [, l] = r, incProgress(), c = handleMaxWidthOrHeight(l, t), incProgress(), new Promise(function (r, i) {
                var o;
                if (!(o = t.exifOrientation)) return getExifOrientation(e).then(function (e) {
                  try {
                    return o = e, $If_2.call(this)
                  } catch (e) {
                    return i(e)
                  }
                }.bind(this), i);

                function $If_2() {
                  return r(o)
                }

                return $If_2.call(this)
              }).then(function (r) {
                try {
                  return u = r, incProgress(), isAutoOrientationInBrowser().then(function (r) {
                    try {
                      return h = r ? c : followExifOrientation(c, u), incProgress(), d = t.initialQuality || 1, A = t.fileType || e.type, canvasToFile(h, A, e.name, e.lastModified, d).then(function (r) {
                        try {
                          {
                            if (g = r, incProgress(), p = g.size > f, m = g.size > e.size, !p && !m) return setProgress(100), i(g);
                            var a;

                            function $Loop_3() {
                              if (s-- && (b > f || b > w)) {
                                let t, r;
                                return t = B ? .95 * _.width : _.width, r = B ? .95 * _.height : _.height, [E, F] = getNewCanvasAndCtx(t, r), F.drawImage(_, 0, 0, t, r), d *= "image/png" === A ? .85 : .95, canvasToFile(E, A, e.name, e.lastModified, d).then(function (e) {
                                  try {
                                    return y = e, cleanupCanvasMemory(_), _ = E, b = y.size, setProgress(Math.min(99, Math.floor((v - b) / (v - f) * 100))), $Loop_3
                                  } catch (e) {
                                    return o(e)
                                  }
                                }, o)
                              }
                              return [1]
                            }

                            return w = e.size, v = g.size, b = v, _ = h, B = !t.alwaysKeepResolution && p, (a = function (e) {
                              for (; e;) {
                                if (e.then) return void e.then(a, o);
                                try {
                                  if (e.pop) {
                                    if (e.length) return e.pop() ? $Loop_3_exit.call(this) : e;
                                    e = $Loop_3
                                  } else e = e.call(this)
                                } catch (e) {
                                  return o(e)
                                }
                              }
                            }.bind(this))($Loop_3);

                            function $Loop_3_exit() {
                              return cleanupCanvasMemory(_), cleanupCanvasMemory(E), cleanupCanvasMemory(c), cleanupCanvasMemory(h), cleanupCanvasMemory(l), setProgress(100), i(y)
                            }
                          }
                        } catch (u) {
                          return o(u)
                        }
                      }.bind(this), o)
                    } catch (e) {
                      return o(e)
                    }
                  }.bind(this), o)
                } catch (e) {
                  return o(e)
                }
              }.bind(this), o)
            } catch (e) {
              return o(e)
            }
          }.bind(this), o)
        })
      }

      const f = "\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n  const { file, id, imageCompressionLibUrl, options } = e.data\n  options.onProgress = (progress) => self.postMessage({ progress, id })\n  try {\n    if (!scriptImported) {\n      // console.log('[worker] importScripts', imageCompressionLibUrl)\n      self.importScripts(imageCompressionLibUrl)\n      scriptImported = true\n    }\n    // console.log('[worker] self', self)\n    const compressedFile = await imageCompression(file, options)\n    self.postMessage({ file: compressedFile, id })\n  } catch (e) {\n    // console.error('[worker] error', e)\n    self.postMessage({ error: e.message + '\\n' + e.stack, id })\n  }\n})\n";
      let l;

      function compressOnWebWorker(e, t) {
        return new Promise((r, i) => {
          l || (l = function createWorkerScriptURL(e) {
            const t = [];
            return "function" == typeof e ? t.push(`(${e})()`) : t.push(e), URL.createObjectURL(new Blob(t))
          }(f));
          const o = new Worker(l);
          o.addEventListener("message", function handler(e) {
            if (t.signal && t.signal.aborted) o.terminate(); else if (void 0 === e.data.progress) {
              if (e.data.error) return i(new Error(e.data.error)), void o.terminate();
              r(e.data.file), o.terminate()
            } else t.onProgress(e.data.progress)
          }), o.addEventListener("error", i), t.signal && t.signal.addEventListener("abort", () => {
            i(t.signal.reason), o.terminate()
          }), o.postMessage({file: e, imageCompressionLibUrl: t.libURL, options: {...t, onProgress: void 0, signal: void 0}})
        })
      }

      function imageCompression(e, t) {
        return new Promise(function (r, i) {
          let o, a, s, f, l, c;
          if (o = {...t}, s = 0, {onProgress: f} = o, o.maxSizeMB = o.maxSizeMB || Number.POSITIVE_INFINITY, l = "boolean" != typeof o.useWebWorker || o.useWebWorker, delete o.useWebWorker, o.onProgress = e => {
            s = e, "function" == typeof f && f(s)
          }, !(1 || e instanceof Blob || e instanceof CustomFile)) return i(new Error("The file given is not an instance of Blob or File"));
          if (!/^image/.test(e.type)) return i(new Error("The file given is not an image"));
          if (c = "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope, !l || "function" != typeof Worker || c) return compress(e, o).then(function (e) {
            try {
              return a = e, $If_4.call(this)
            } catch (e) {
              return i(e)
            }
          }.bind(this), i);
          var u = function () {
            try {
              return $If_4.call(this)
            } catch (e) {
              return i(e)
            }
          }.bind(this), $Try_1_Catch = function (t) {
            try {
              return compress(e, o).then(function (e) {
                try {
                  return a = e, u()
                } catch (e) {
                  return i(e)
                }
              }, i)
            } catch (e) {
              return i(e)
            }
          };
          try {
            return o.libURL = o.libURL || "https://cdn.bootcdn.net/ajax/libs/browser-image-compression/2.0.2/browser-image-compression.js", compressOnWebWorker(e, o).then(function (e) {
              try {
                return a = e, u()
              } catch (e) {
                return $Try_1_Catch()
              }
            }, $Try_1_Catch)
          } catch (e) {
            $Try_1_Catch()
          }

          function $If_4() {
            try {
              a.name = e.name, a.lastModified = e.lastModified
            } catch (e) {
            }
            try {
              o.preserveExif && "image/jpeg" === e.type && (!o.fileType || o.fileType && o.fileType === e.type) && (a = copyExifWithoutOrientation(e, a))
            } catch (e) {
            }
            return r(a)
          }
        })
      }

      return imageCompression.getDataUrlFromFile = getDataUrlFromFile, imageCompression.getFilefromDataUrl = getFilefromDataUrl, imageCompression.loadImage = loadImage, imageCompression.drawImageInCanvas = drawImageInCanvas, imageCompression.drawFileInCanvas = drawFileInCanvas, imageCompression.canvasToFile = canvasToFile, imageCompression.getExifOrientation = getExifOrientation, imageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight, imageCompression.followExifOrientation = followExifOrientation, imageCompression.cleanupCanvasMemory = cleanupCanvasMemory, imageCompression.isAutoOrientationInBrowser = isAutoOrientationInBrowser, imageCompression.approximateBelowMaximumCanvasSizeOfBrowser = approximateBelowMaximumCanvasSizeOfBrowser, imageCompression.copyExifWithoutOrientation = copyExifWithoutOrientation, imageCompression.getBrowserName = getBrowserName, imageCompression.version = "2.0.2", imageCompression
    });
    return {
      compress: function (file, option) {
        return imageCompression(file, option)
      }
    }
  }();
  UE.dialog = function () {
    return {
      loadingPlaceholder: function (me) {
        var loadingId = "loading_" + (+new Date).toString(36);
        me.focus();
        me.execCommand("inserthtml", '<img class="uep-loading" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif">');
        return loadingId
      }, removeLoadingPlaceholder: function (me, loadingId) {
        var loader = me.document.getElementById(loadingId);
        if (loader) {
          domUtils.remove(loader, false)
        }
      }, tipError: function (me, title) {
        me.fireEvent("showmessage", {content: title, type: "error", timeout: 4e3})
      }
    }
  }();
  var filterWord = UE.filterWord = function () {
    function isWordDocument(str) {
      return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/gi.test(str)
    }

    function transUnit(v) {
      v = v.replace(/[\d.]+\w+/g, function (m) {
        return utils.transUnitToPx(m)
      });
      return v
    }

    function filterPasteWord(str) {
      return str.replace(/[\t\r\n]+/g, " ").replace(/<!--[\s\S]*?-->/gi, "").replace(/<v:shape [^>]*>[\s\S]*?.<\/v:shape>/gi, function (str) {
        if (browser.opera) {
          return ""
        }
        try {
          if (/Bitmap/i.test(str)) {
            return ""
          }
          var width = str.match(/width:([ \d.]*p[tx])/i)[1], height = str.match(/height:([ \d.]*p[tx])/i)[1], src = str.match(/src=\s*"([^"]*)"/i)[1];
          return '<img width="' + transUnit(width) + '" height="' + transUnit(height) + '" src="' + src + '" />'
        } catch (e) {
          return ""
        }
      }).replace(/<\/?div[^>]*>/g, "").replace(/v:\w+=(["']?)[^'"]+\1/g, "").replace(/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "").replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "<p><strong>$1</strong></p>").replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/gi, function (str, name, marks, val) {
        return name == "class" && val == "MsoListParagraph" ? str : ""
      }).replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function (a, b, c) {
        return c.replace(/[\t\r\n ]+/g, " ")
      }).replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function (str, tag, tmp, style) {
        var n = [], s = style.replace(/^\s+|\s+$/, "").replace(/&#39;/g, "'").replace(/&quot;/gi, "'").replace(/[\d.]+(cm|pt)/g, function (str) {
          return utils.transUnitToPx(str)
        }).split(/;\s*/g);
        for (var i = 0, v; v = s[i]; i++) {
          var name, value, parts = v.split(":");
          if (parts.length == 2) {
            name = parts[0].toLowerCase();
            value = parts[1].toLowerCase();
            if (/^(background)\w*/.test(name) && value.replace(/(initial|\s)/g, "").length == 0 || /^(margin)\w*/.test(name) && /^0\w+$/.test(value)) {
              continue
            }
            switch (name) {
              case"mso-padding-alt":
              case"mso-padding-top-alt":
              case"mso-padding-right-alt":
              case"mso-padding-bottom-alt":
              case"mso-padding-left-alt":
              case"mso-margin-alt":
              case"mso-margin-top-alt":
              case"mso-margin-right-alt":
              case"mso-margin-bottom-alt":
              case"mso-margin-left-alt":
              case"mso-height":
              case"mso-width":
              case"mso-vertical-align-alt":
                if (!/<table/.test(tag)) n[i] = name.replace(/^mso-|-alt$/g, "") + ":" + transUnit(value);
                continue;
              case"horiz-align":
                n[i] = "text-align:" + value;
                continue;
              case"vert-align":
                n[i] = "vertical-align:" + value;
                continue;
              case"font-color":
              case"mso-foreground":
                n[i] = "color:" + value;
                continue;
              case"mso-background":
              case"mso-highlight":
                n[i] = "background:" + value;
                continue;
              case"mso-default-height":
                n[i] = "min-height:" + transUnit(value);
                continue;
              case"mso-default-width":
                n[i] = "min-width:" + transUnit(value);
                continue;
              case"mso-padding-between-alt":
                n[i] = "border-collapse:separate;border-spacing:" + transUnit(value);
                continue;
              case"text-line-through":
                if (value == "single" || value == "double") {
                  n[i] = "text-decoration:line-through"
                }
                continue;
              case"mso-zero-height":
                if (value == "yes") {
                  n[i] = "display:none"
                }
                continue;
              case"margin":
                if (!/[1-9]/.test(value)) {
                  continue
                }
            }
            if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?:decor|trans)|top-bar|version|vnd|word-break)/.test(name) || /text\-indent|padding|margin/.test(name) && /\-[\d.]+/.test(value)) {
              continue
            }
            n[i] = name + ":" + parts[1]
          }
        }
        return tag + (n.length ? ' style="' + n.join(";").replace(/;{2,}/g, ";") + '"' : "")
      })
    }

    return function (html) {
      return isWordDocument(html) ? filterPasteWord(html) : html
    }
  }();
  (function () {
    var uNode = UE.uNode = function (obj) {
      this.type = obj.type;
      this.data = obj.data;
      this.tagName = obj.tagName;
      this.parentNode = obj.parentNode;
      this.attrs = obj.attrs || {};
      this.children = obj.children
    };
    var notTransAttrs = {href: 1, src: 1, _src: 1, _href: 1, cdata_data: 1};
    var notTransTagName = {style: 1, script: 1};
    var indentChar = "    ", breakChar = "\n";

    function insertLine(arr, current, begin) {
      arr.push(breakChar);
      return current + (begin ? 1 : -1)
    }

    function insertIndent(arr, current) {
      for (var i = 0; i < current; i++) {
        arr.push(indentChar)
      }
    }

    uNode.createElement = function (html) {
      if (/[<>]/.test(html)) {
        return UE.htmlparser(html).children[0]
      } else {
        return new uNode({type: "element", children: [], tagName: html})
      }
    };
    uNode.createText = function (data, noTrans) {
      return new UE.uNode({type: "text", data: noTrans ? data : utils.unhtml(data || "")})
    };

    function nodeToHtml(node, arr, formatter, current) {
      switch (node.type) {
        case"root":
          for (var i = 0, ci; ci = node.children[i++];) {
            if (formatter && ci.type == "element" && !dtd.$inlineWithA[ci.tagName] && i > 1) {
              insertLine(arr, current, true);
              insertIndent(arr, current)
            }
            nodeToHtml(ci, arr, formatter, current)
          }
          break;
        case"text":
          isText(node, arr);
          break;
        case"element":
          isElement(node, arr, formatter, current);
          break;
        case"comment":
          isComment(node, arr, formatter)
      }
      return arr
    }

    function isText(node, arr) {
      if (node.parentNode.tagName == "pre") {
        arr.push(node.data)
      } else {
        arr.push(notTransTagName[node.parentNode.tagName] ? utils.html(node.data) : node.data.replace(/[ ]{2}/g, " &nbsp;"))
      }
    }

    function isElement(node, arr, formatter, current) {
      var attrhtml = "";
      if (node.attrs) {
        attrhtml = [];
        var attrs = node.attrs;
        for (var a in attrs) {
          attrhtml.push(a + (attrs[a] !== undefined ? '="' + (notTransAttrs[a] ? utils.html(attrs[a]).replace(/["]/g, function (a) {
            return "&quot;"
          }) : utils.unhtml(attrs[a])) + '"' : ""))
        }
        attrhtml = attrhtml.join(" ")
      }
      arr.push("<" + node.tagName + (attrhtml ? " " + attrhtml : "") + (dtd.$empty[node.tagName] ? "/" : "") + ">");
      if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") {
        if (node.children && node.children.length) {
          current = insertLine(arr, current, true);
          insertIndent(arr, current)
        }
      }
      if (node.children && node.children.length) {
        for (var i = 0, ci; ci = node.children[i++];) {
          if (formatter && ci.type == "element" && !dtd.$inlineWithA[ci.tagName] && i > 1) {
            insertLine(arr, current);
            insertIndent(arr, current)
          }
          nodeToHtml(ci, arr, formatter, current)
        }
      }
      if (!dtd.$empty[node.tagName]) {
        if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") {
          if (node.children && node.children.length) {
            current = insertLine(arr, current);
            insertIndent(arr, current)
          }
        }
        arr.push("</" + node.tagName + ">")
      }
    }

    function isComment(node, arr) {
      arr.push("\x3c!--" + node.data + "--\x3e")
    }

    function getNodeById(root, id) {
      var node;
      if (root.type == "element" && root.getAttr("id") == id) {
        return root
      }
      if (root.children && root.children.length) {
        for (var i = 0, ci; ci = root.children[i++];) {
          if (node = getNodeById(ci, id)) {
            return node
          }
        }
      }
    }

    function getNodesByTagName(node, tagName, arr) {
      if (node.type == "element" && node.tagName == tagName) {
        arr.push(node)
      }
      if (node.children && node.children.length) {
        for (var i = 0, ci; ci = node.children[i++];) {
          getNodesByTagName(ci, tagName, arr)
        }
      }
    }

    function nodeTraversal(root, fn) {
      if (root.children && root.children.length) {
        for (var i = 0, ci; ci = root.children[i];) {
          nodeTraversal(ci, fn);
          if (ci.parentNode) {
            if (ci.children && ci.children.length) {
              fn(ci)
            }
            if (ci.parentNode) i++
          }
        }
      } else {
        fn(root)
      }
    }

    uNode.prototype = {
      toHtml: function (formatter) {
        var arr = [];
        nodeToHtml(this, arr, formatter, 0);
        return arr.join("")
      }, innerHTML: function (htmlstr) {
        if (this.type != "element" || dtd.$empty[this.tagName]) {
          return this
        }
        if (utils.isString(htmlstr)) {
          if (this.children) {
            for (var i = 0, ci; ci = this.children[i++];) {
              ci.parentNode = null
            }
          }
          this.children = [];
          var tmpRoot = UE.htmlparser(htmlstr);
          for (var i = 0, ci; ci = tmpRoot.children[i++];) {
            this.children.push(ci);
            ci.parentNode = this
          }
          return this
        } else {
          var tmpRoot = new UE.uNode({type: "root", children: this.children});
          return tmpRoot.toHtml()
        }
      }, innerText: function (textStr, noTrans) {
        if (this.type != "element" || dtd.$empty[this.tagName]) {
          return this
        }
        if (textStr) {
          if (this.children) {
            for (var i = 0, ci; ci = this.children[i++];) {
              ci.parentNode = null
            }
          }
          this.children = [];
          this.appendChild(uNode.createText(textStr, noTrans));
          return this
        } else {
          return this.toHtml().replace(/<[^>]+>/g, "")
        }
      }, getData: function () {
        if (this.type == "element") return "";
        return this.data
      }, firstChild: function () {
        return this.children ? this.children[0] : null
      }, lastChild: function () {
        return this.children ? this.children[this.children.length - 1] : null
      }, previousSibling: function () {
        var parent = this.parentNode;
        for (var i = 0, ci; ci = parent.children[i]; i++) {
          if (ci === this) {
            return i == 0 ? null : parent.children[i - 1]
          }
        }
      }, nextSibling: function () {
        var parent = this.parentNode;
        for (var i = 0, ci; ci = parent.children[i++];) {
          if (ci === this) {
            return parent.children[i]
          }
        }
      }, replaceChild: function (target, source) {
        if (this.children) {
          if (target.parentNode) {
            target.parentNode.removeChild(target)
          }
          for (var i = 0, ci; ci = this.children[i]; i++) {
            if (ci === source) {
              this.children.splice(i, 1, target);
              source.parentNode = null;
              target.parentNode = this;
              return target
            }
          }
        }
      }, appendChild: function (node) {
        if (this.type == "root" || this.type == "element" && !dtd.$empty[this.tagName]) {
          if (!this.children) {
            this.children = []
          }
          if (node.parentNode) {
            node.parentNode.removeChild(node)
          }
          for (var i = 0, ci; ci = this.children[i]; i++) {
            if (ci === node) {
              this.children.splice(i, 1);
              break
            }
          }
          this.children.push(node);
          node.parentNode = this;
          return node
        }
      }, insertBefore: function (target, source) {
        if (this.children) {
          if (target.parentNode) {
            target.parentNode.removeChild(target)
          }
          for (var i = 0, ci; ci = this.children[i]; i++) {
            if (ci === source) {
              this.children.splice(i, 0, target);
              target.parentNode = this;
              return target
            }
          }
        }
      }, insertAfter: function (target, source) {
        if (this.children) {
          if (target.parentNode) {
            target.parentNode.removeChild(target)
          }
          for (var i = 0, ci; ci = this.children[i]; i++) {
            if (ci === source) {
              this.children.splice(i + 1, 0, target);
              target.parentNode = this;
              return target
            }
          }
        }
      }, removeChild: function (node, keepChildren) {
        if (this.children) {
          for (var i = 0, ci; ci = this.children[i]; i++) {
            if (ci === node) {
              this.children.splice(i, 1);
              ci.parentNode = null;
              if (keepChildren && ci.children && ci.children.length) {
                for (var j = 0, cj; cj = ci.children[j]; j++) {
                  this.children.splice(i + j, 0, cj);
                  cj.parentNode = this
                }
              }
              return ci
            }
          }
        }
      }, getAttr: function (attrName) {
        return this.attrs && this.attrs[attrName.toLowerCase()]
      }, setAttr: function (attrName, attrVal) {
        if (!attrName) {
          delete this.attrs;
          return
        }
        if (!this.attrs) {
          this.attrs = {}
        }
        if (utils.isObject(attrName)) {
          for (var a in attrName) {
            if (!attrName[a]) {
              delete this.attrs[a]
            } else {
              this.attrs[a.toLowerCase()] = attrName[a]
            }
          }
        } else {
          if (!attrVal) {
            delete this.attrs[attrName]
          } else {
            this.attrs[attrName.toLowerCase()] = attrVal
          }
        }
      }, getIndex: function () {
        var parent = this.parentNode;
        for (var i = 0, ci; ci = parent.children[i]; i++) {
          if (ci === this) {
            return i
          }
        }
        return -1
      }, getNodeById: function (id) {
        var node;
        if (this.children && this.children.length) {
          for (var i = 0, ci; ci = this.children[i++];) {
            if (node = getNodeById(ci, id)) {
              return node
            }
          }
        }
      }, getNodesByTagName: function (tagNames) {
        tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, " ").split(" ");
        var arr = [], me = this;
        utils.each(tagNames, function (tagName) {
          if (me.children && me.children.length) {
            for (var i = 0, ci; ci = me.children[i++];) {
              getNodesByTagName(ci, tagName, arr)
            }
          }
        });
        return arr
      }, getStyle: function (name) {
        var cssStyle = this.getAttr("style");
        if (!cssStyle) {
          return ""
        }
        var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+)", "i");
        var match = cssStyle.match(reg);
        if (match && match[0]) {
          return match[2]
        }
        return ""
      }, setStyle: function (name, val) {
        function exec(name, val) {
          var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+;?)", "gi");
          cssStyle = cssStyle.replace(reg, "$1");
          if (val) {
            cssStyle = name + ":" + utils.unhtml(val) + ";" + cssStyle
          }
        }

        var cssStyle = this.getAttr("style");
        if (!cssStyle) {
          cssStyle = ""
        }
        if (utils.isObject(name)) {
          for (var a in name) {
            exec(a, name[a])
          }
        } else {
          exec(name, val)
        }
        this.setAttr("style", utils.trim(cssStyle))
      }, traversal: function (fn) {
        if (this.children && this.children.length) {
          nodeTraversal(this, fn)
        }
        return this
      }
    }
  })();
  var htmlparser = UE.htmlparser = function (htmlstr, ignoreBlank) {
    var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g,
      re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
    var allowEmptyTags = {b: 1, code: 1, i: 1, u: 1, strike: 1, s: 1, tt: 1, strong: 1, q: 1, samp: 1, em: 1, span: 1, sub: 1, img: 1, sup: 1, font: 1, big: 1, small: 1, iframe: 1, a: 1, br: 1, pre: 1};
    htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), "");
    if (!ignoreBlank) {
      htmlstr = htmlstr.replace(new RegExp("[\\r\\t\\n" + (ignoreBlank ? "" : " ") + "]*</?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n" + (ignoreBlank ? "" : " ") + "]*", "g"), function (a, b) {
        if (b && allowEmptyTags[b.toLowerCase()]) {
          return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, "")
        }
        return a.replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "").replace(new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"), "")
      })
    }
    var notTransAttrs = {href: 1, src: 1};
    var uNode = UE.uNode, needParentNode = {td: "tr", tr: ["tbody", "thead", "tfoot"], tbody: "table", th: "tr", thead: "table", tfoot: "table", caption: "table", li: ["ul", "ol"], dt: "dl", dd: "dl", option: "select"},
      needChild = {ol: "li", ul: "li"};

    function text(parent, data) {
      if (needChild[parent.tagName]) {
        var tmpNode = uNode.createElement(needChild[parent.tagName]);
        parent.appendChild(tmpNode);
        tmpNode.appendChild(uNode.createText(data));
        parent = tmpNode
      } else {
        parent.appendChild(uNode.createText(data))
      }
    }

    function element(parent, tagName, htmlattr) {
      var needParentTag;
      if (needParentTag = needParentNode[tagName]) {
        var tmpParent = parent, hasParent;
        while (tmpParent.type != "root") {
          if (utils.isArray(needParentTag) ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 : needParentTag == tmpParent.tagName) {
            parent = tmpParent;
            hasParent = true;
            break
          }
          tmpParent = tmpParent.parentNode
        }
        if (!hasParent) {
          parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag)
        }
      }
      var elm = new uNode({parentNode: parent, type: "element", tagName: tagName.toLowerCase(), children: dtd.$empty[tagName] ? null : []});
      if (htmlattr) {
        var attrs = {}, match;
        while (match = re_attr.exec(htmlattr)) {
          attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] ? match[2] || match[3] || match[4] : utils.unhtml(match[2] || match[3] || match[4])
        }
        elm.attrs = attrs
      }
      parent.children.push(elm);
      return dtd.$empty[tagName] ? parent : elm
    }

    function comment(parent, data) {
      parent.children.push(new uNode({type: "comment", data: data, parentNode: parent}))
    }

    var match, currentIndex = 0, nextIndex = 0;
    var root = new uNode({type: "root", children: []});
    var currentParent = root;
    while (match = re_tag.exec(htmlstr)) {
      currentIndex = match.index;
      try {
        if (currentIndex > nextIndex) {
          text(currentParent, htmlstr.slice(nextIndex, currentIndex))
        }
        if (match[3]) {
          if (dtd.$cdata[currentParent.tagName]) {
            text(currentParent, match[0])
          } else {
            currentParent = element(currentParent, match[3].toLowerCase(), match[4])
          }
        } else if (match[1]) {
          if (currentParent.type != "root") {
            if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
              text(currentParent, match[0])
            } else {
              var tmpParent = currentParent;
              while (currentParent.type == "element" && currentParent.tagName != match[1].toLowerCase()) {
                currentParent = currentParent.parentNode;
                if (currentParent.type == "root") {
                  currentParent = tmpParent;
                  throw"break"
                }
              }
              currentParent = currentParent.parentNode
            }
          }
        } else if (match[2]) {
          comment(currentParent, match[2])
        }
      } catch (e) {
      }
      nextIndex = re_tag.lastIndex
    }
    if (nextIndex < htmlstr.length) {
      text(currentParent, htmlstr.slice(nextIndex))
    }
    return root
  };
  var filterNode = UE.filterNode = function () {
    function filterNode(node, rules) {
      switch (node.type) {
        case"text":
          break;
        case"element":
          var val;
          if (val = rules[node.tagName]) {
            if (val === "-") {
              node.parentNode.removeChild(node)
            } else if (utils.isFunction(val)) {
              var parentNode = node.parentNode, index = node.getIndex();
              val(node);
              if (node.parentNode) {
                if (node.children) {
                  for (var i = 0, ci; ci = node.children[i];) {
                    filterNode(ci, rules);
                    if (ci.parentNode) {
                      i++
                    }
                  }
                }
              } else {
                for (var i = index, ci; ci = parentNode.children[i];) {
                  filterNode(ci, rules);
                  if (ci.parentNode) {
                    i++
                  }
                }
              }
            } else {
              var attrs = val["$"];
              if (attrs && node.attrs) {
                var tmpAttrs = {}, tmpVal;
                for (var a in attrs) {
                  tmpVal = node.getAttr(a);
                  if (a == "style" && utils.isArray(attrs[a])) {
                    var tmpCssStyle = [];
                    utils.each(attrs[a], function (v) {
                      var tmp;
                      if (tmp = node.getStyle(v)) {
                        tmpCssStyle.push(v + ":" + tmp)
                      }
                    });
                    tmpVal = tmpCssStyle.join(";")
                  }
                  if (tmpVal) {
                    tmpAttrs[a] = tmpVal
                  }
                }
                node.attrs = tmpAttrs
              }
              if (node.children) {
                for (var i = 0, ci; ci = node.children[i];) {
                  filterNode(ci, rules);
                  if (ci.parentNode) {
                    i++
                  }
                }
              }
            }
          } else {
            if (dtd.$cdata[node.tagName]) {
              node.parentNode.removeChild(node)
            } else {
              var parentNode = node.parentNode, index = node.getIndex();
              node.parentNode.removeChild(node, true);
              for (var i = index, ci; ci = parentNode.children[i];) {
                filterNode(ci, rules);
                if (ci.parentNode) {
                  i++
                }
              }
            }
          }
          break;
        case"comment":
          node.parentNode.removeChild(node)
      }
    }

    return function (root, rules) {
      if (utils.isEmptyObject(rules)) {
        return root
      }
      var val;
      if (val = rules["-"]) {
        utils.each(val.split(" "), function (k) {
          rules[k] = "-"
        })
      }
      for (var i = 0, ci; ci = root.children[i];) {
        filterNode(ci, rules);
        if (ci.parentNode) {
          i++
        }
      }
      return root
    }
  }();
  UE.plugin = function () {
    var _plugins = {};
    return {
      register: function (pluginName, fn, oldOptionName, afterDisabled) {
        if (oldOptionName && utils.isFunction(oldOptionName)) {
          afterDisabled = oldOptionName;
          oldOptionName = null
        }
        _plugins[pluginName] = {optionName: oldOptionName || pluginName, execFn: fn, afterDisabled: afterDisabled}
      }, load: function (editor) {
        utils.each(_plugins, function (plugin) {
          var _export = plugin.execFn.call(editor);
          if (editor.options[plugin.optionName] !== false) {
            if (_export) {
              utils.each(_export, function (v, k) {
                switch (k.toLowerCase()) {
                  case"shortcutkey":
                    editor.addshortcutkey(v);
                    break;
                  case"bindevents":
                    utils.each(v, function (fn, eventName) {
                      editor.addListener(eventName, fn)
                    });
                    break;
                  case"bindmultievents":
                    utils.each(utils.isArray(v) ? v : [v], function (event) {
                      var types = utils.trim(event.type).split(/\s+/);
                      utils.each(types, function (eventName) {
                        editor.addListener(eventName, event.handler)
                      })
                    });
                    break;
                  case"commands":
                    utils.each(v, function (execFn, execName) {
                      editor.commands[execName] = execFn
                    });
                    break;
                  case"outputrule":
                    editor.addOutputRule(v);
                    break;
                  case"inputrule":
                    editor.addInputRule(v);
                    break;
                  case"defaultoptions":
                    editor.setOpt(v)
                }
              })
            }
          } else if (plugin.afterDisabled) {
            plugin.afterDisabled.call(editor)
          }
        });
        utils.each(UE.plugins, function (plugin) {
          plugin.call(editor)
        })
      }, run: function (pluginName, editor) {
        var plugin = _plugins[pluginName];
        if (plugin) {
          plugin.exeFn.call(editor)
        }
      }
    }
  }();
  var keymap = UE.keymap = {
    Backspace: 8,
    Tab: 9,
    Enter: 13,
    Shift: 16,
    Control: 17,
    Alt: 18,
    CapsLock: 20,
    Esc: 27,
    Spacebar: 32,
    PageUp: 33,
    PageDown: 34,
    End: 35,
    Home: 36,
    Left: 37,
    Up: 38,
    Right: 39,
    Down: 40,
    Insert: 45,
    Del: 46,
    NumLock: 144,
    Cmd: 91,
    "=": 187,
    "-": 189,
    b: 66,
    i: 73,
    z: 90,
    y: 89,
    v: 86,
    x: 88,
    s: 83,
    n: 78
  };
  var LocalStorage = UE.LocalStorage = function () {
    var storage = window.localStorage;
    return {
      saveLocalData: function (key, data) {
        if (!storage) {
          return false
        }
        storage.setItem(key, data);
        return true
      }, getLocalData: function (key) {
        if (!storage) {
          return null
        }
        return storage.getItem(key) || null
      }, removeItem: function (key) {
        storage && storage.removeItem(key)
      }
    }
  }();
  (function () {
    var ROOT_KEY = "UEditorPlusPref";
    UE.Editor.prototype.setPreferences = function (key, value) {
      var obj = {};
      if (utils.isString(key)) {
        obj[key] = value
      } else {
        obj = key
      }
      var data = LocalStorage.getLocalData(ROOT_KEY);
      if (data && (data = utils.str2json(data))) {
        utils.extend(data, obj)
      } else {
        data = obj
      }
      data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data))
    };
    UE.Editor.prototype.getPreferences = function (key) {
      var data = LocalStorage.getLocalData(ROOT_KEY);
      if (data && (data = utils.str2json(data))) {
        return key ? data[key] : data
      }
      return null
    };
    UE.Editor.prototype.removePreferences = function (key) {
      var data = LocalStorage.getLocalData(ROOT_KEY);
      if (data && (data = utils.str2json(data))) {
        data[key] = undefined;
        delete data[key]
      }
      data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data))
    }
  })();
  UE.plugins["defaultfilter"] = function () {
    var me = this;
    me.setOpt({allowDivTransToP: true, disabledTableInTable: true, rgb2Hex: true});
    me.addInputRule(function (root) {
      var allowDivTransToP = this.options.allowDivTransToP;
      var val;

      function tdParent(node) {
        while (node && node.type == "element") {
          if (node.tagName == "td") {
            return true
          }
          node = node.parentNode
        }
        return false
      }

      root.traversal(function (node) {
        if (node.type == "element") {
          if (!dtd.$cdata[node.tagName] && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
            if (!node.firstChild()) node.parentNode.removeChild(node); else if (node.tagName == "span" && (!node.attrs || utils.isEmptyObject(node.attrs))) {
              node.parentNode.removeChild(node, true)
            }
            return
          }
          switch (node.tagName) {
            case"style":
            case"script":
              node.setAttr({cdata_tag: node.tagName, cdata_data: node.innerHTML() || "", _ue_custom_node_: "true"});
              node.tagName = "div";
              node.innerHTML("");
              break;
            case"a":
              if (val = node.getAttr("href")) {
                node.setAttr("_href", val)
              }
              break;
            case"img":
              // if (val = node.getAttr("src")) {
              //   if (/^data:/.test(val)) {
              //     node.parentNode.removeChild(node);
              //     break
              //   }
              // }
              // node.setAttr("_src", node.getAttr("src"));
              // break;
            case"span":
              if (browser.webkit && (val = node.getStyle("white-space"))) {
                if (/nowrap|normal/.test(val)) {
                  node.setStyle("white-space", "");
                  if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) {
                    node.parentNode.removeChild(node, true)
                  }
                }
              }
              val = node.getAttr("id");
              if (val && /^_baidu_bookmark_/i.test(val)) {
                node.parentNode.removeChild(node)
              }
              break;
            case"p":
              if (val = node.getAttr("align")) {
                node.setAttr("align");
                node.setStyle("text-align", val)
              }
              utils.each(node.children, function (n) {
                if (n.type == "element" && n.tagName == "p") {
                  var next = n.nextSibling();
                  node.parentNode.insertAfter(n, node);
                  var last = n;
                  while (next) {
                    var tmp = next.nextSibling();
                    node.parentNode.insertAfter(next, last);
                    last = next;
                    next = tmp
                  }
                  return false
                }
              });
              if (!node.firstChild()) {
                node.innerHTML(browser.ie ? "&nbsp;" : "<br/>")
              }
              break;
            case"div":
              if (node.getAttr("cdata_tag")) {
                break
              }
              val = node.getAttr("class");
              if (val && /^line number\d+/.test(val)) {
                break
              }
              if (!allowDivTransToP) {
                break
              }
              var tmpNode, p = UE.uNode.createElement("p");
              while (tmpNode = node.firstChild()) {
                if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) {
                  p.appendChild(tmpNode)
                } else {
                  if (p.firstChild()) {
                    node.parentNode.insertBefore(p, node);
                    p = UE.uNode.createElement("p")
                  } else {
                    node.parentNode.insertBefore(tmpNode, node)
                  }
                }
              }
              if (p.firstChild()) {
                node.parentNode.insertBefore(p, node)
              }
              node.parentNode.removeChild(node);
              break;
            case"dl":
              node.tagName = "ul";
              break;
            case"dt":
            case"dd":
              node.tagName = "li";
              break;
            case"li":
              var className = node.getAttr("class");
              if (!className || !/list\-/.test(className)) {
                node.setAttr()
              }
              var tmpNodes = node.getNodesByTagName("ol ul");
              UE.utils.each(tmpNodes, function (n) {
                node.parentNode.insertAfter(n, node)
              });
              break;
            case"td":
            case"th":
            case"caption":
              if (!node.children || !node.children.length) {
                node.appendChild(browser.ie11below ? UE.uNode.createText(" ") : UE.uNode.createElement("br"))
              }
              break;
            case"table":
              if (me.options.disabledTableInTable && tdParent(node)) {
                node.parentNode.insertBefore(UE.uNode.createText(node.innerText()), node);
                node.parentNode.removeChild(node)
              }
          }
        }
      })
    });
    me.addOutputRule(function (root) {
      var val;
      root.traversal(function (node) {
        if (node.type == "element") {
          if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
            if (!node.firstChild()) node.parentNode.removeChild(node); else if (node.tagName == "span" && (!node.attrs || utils.isEmptyObject(node.attrs))) {
              node.parentNode.removeChild(node, true)
            }
            return
          }
          switch (node.tagName) {
            case"div":
              if (val = node.getAttr("cdata_tag")) {
                node.tagName = val;
                node.appendChild(UE.uNode.createText(node.getAttr("cdata_data")));
                node.setAttr({cdata_tag: "", cdata_data: "", _ue_custom_node_: ""})
              }
              break;
            case"a":
              if (val = node.getAttr("_href")) {
                node.setAttr({href: utils.html(val), _href: ""})
              }
              break;
              break;
            case"span":
              val = node.getAttr("id");
              if (val && /^_baidu_bookmark_/i.test(val)) {
                node.parentNode.removeChild(node)
              }
              if (me.getOpt("rgb2Hex")) {
                var cssStyle = node.getAttr("style");
                if (cssStyle) {
                  node.setAttr("style", cssStyle.replace(/rgba?\(([\d,\s]+)\)/g, function (a, value) {
                    var array = value.split(",");
                    if (array.length > 3) return "";
                    value = "#";
                    for (var i = 0, color; color = array[i++];) {
                      color = parseInt(color.replace(/[^\d]/gi, ""), 10).toString(16);
                      value += color.length == 1 ? "0" + color : color
                    }
                    return value.toUpperCase()
                  }))
                }
              }
              break;
            case"img":
              if (val = node.getAttr("_src")) {
                node.setAttr({src: node.getAttr("_src"), _src: ""})
              }
          }
        }
      })
    })
  };
  UE.commands["inserthtml"] = {
    execCommand: function (command, html, notNeedFilter) {
      var me = this, range, div;
      if (!html) {
        return
      }
      if (me.fireEvent("beforeinserthtml", html) === true) {
        return
      }
      range = me.selection.getRange();
      div = range.document.createElement("div");
      div.style.display = "inline";
      if (!notNeedFilter) {
        var root = UE.htmlparser(html);
        if (me.options.filterRules) {
          UE.filterNode(root, me.options.filterRules)
        }
        me.filterInputRule(root);
        html = root.toHtml()
      }
      div.innerHTML = utils.trim(html);
      if (!range.collapsed) {
        var tmpNode = range.startContainer;
        if (domUtils.isFillChar(tmpNode)) {
          range.setStartBefore(tmpNode)
        }
        tmpNode = range.endContainer;
        if (domUtils.isFillChar(tmpNode)) {
          range.setEndAfter(tmpNode)
        }
        range.txtToElmBoundary();
        if (range.endContainer && range.endContainer.nodeType == 1) {
          tmpNode = range.endContainer.childNodes[range.endOffset];
          if (tmpNode && domUtils.isBr(tmpNode)) {
            range.setEndAfter(tmpNode)
          }
        }
        if (range.startOffset == 0) {
          tmpNode = range.startContainer;
          if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
            tmpNode = range.endContainer;
            if (range.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode, "lastChild")) {
              me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
              range.setStart(me.body.firstChild, 0).collapse(true)
            }
          }
        }
        !range.collapsed && range.deleteContents();
        if (range.startContainer.nodeType == 1) {
          var child = range.startContainer.childNodes[range.startOffset], pre;
          if (child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)) {
            range.setEnd(pre, pre.childNodes.length).collapse();
            while (child.firstChild) {
              pre.appendChild(child.firstChild)
            }
            domUtils.remove(child)
          }
        }
      }
      var child, parent, pre, tmp, hadBreak = 0, nextNode;
      if (range.inFillChar()) {
        child = range.startContainer;
        if (domUtils.isFillChar(child)) {
          range.setStartBefore(child).collapse(true);
          domUtils.remove(child)
        } else if (domUtils.isFillChar(child, true)) {
          child.nodeValue = child.nodeValue.replace(fillCharReg, "");
          range.startOffset--;
          range.collapsed && range.collapse(true)
        }
      }
      var li = domUtils.findParentByTagName(range.startContainer, "li", true);
      if (li) {
        var next, last;
        while (child = div.firstChild) {
          while (child && (child.nodeType == 3 || !domUtils.isBlockElm(child) || child.tagName == "HR")) {
            next = child.nextSibling;
            range.insertNode(child).collapse();
            last = child;
            child = next
          }
          if (child) {
            if (/^(ol|ul)$/i.test(child.tagName)) {
              while (child.firstChild) {
                last = child.firstChild;
                domUtils.insertAfter(li, child.firstChild);
                li = li.nextSibling
              }
              domUtils.remove(child)
            } else {
              var tmpLi;
              next = child.nextSibling;
              tmpLi = me.document.createElement("li");
              domUtils.insertAfter(li, tmpLi);
              tmpLi.appendChild(child);
              last = child;
              child = next;
              li = tmpLi
            }
          }
        }
        li = domUtils.findParentByTagName(range.startContainer, "li", true);
        if (domUtils.isEmptyBlock(li)) {
          domUtils.remove(li)
        }
        if (last) {
          range.setStartAfter(last).collapse(true).select(true)
        }
      } else {
        while (child = div.firstChild) {
          if (hadBreak) {
            var p = me.document.createElement("p");
            while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) {
              nextNode = child.nextSibling;
              p.appendChild(child);
              child = nextNode
            }
            if (p.firstChild) {
              child = p
            }
          }
          range.insertNode(child);
          nextNode = child.nextSibling;
          if (!hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm(child)) {
            parent = domUtils.findParent(child, function (node) {
              return domUtils.isBlockElm(node)
            });
            if (parent && parent.tagName.toLowerCase() != "body" && !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)) {
              if (!dtd[parent.tagName][child.nodeName]) {
                pre = parent
              } else {
                tmp = child.parentNode;
                while (tmp !== parent) {
                  pre = tmp;
                  tmp = tmp.parentNode
                }
              }
              domUtils.breakParent(child, pre || tmp);
              var pre = child.previousSibling;
              domUtils.trimWhiteTextNode(pre);
              if (!pre.childNodes.length) {
                domUtils.remove(pre)
              }
              if (!browser.ie && (next = child.nextSibling) && domUtils.isBlockElm(next) && next.lastChild && !domUtils.isBr(next.lastChild)) {
                next.appendChild(me.document.createElement("br"))
              }
              hadBreak = 1
            }
          }
          var next = child.nextSibling;
          if (!div.firstChild && next && domUtils.isBlockElm(next)) {
            range.setStart(next, 0).collapse(true);
            break
          }
          range.setEndAfter(child).collapse()
        }
        child = range.startContainer;
        if (nextNode && domUtils.isBr(nextNode)) {
          domUtils.remove(nextNode)
        }
        if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) {
          if (nextNode = child.nextSibling) {
            domUtils.remove(child);
            if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) {
              range.setStart(nextNode, 0).collapse(true).shrinkBoundary()
            }
          } else {
            try {
              child.innerHTML = browser.ie ? domUtils.fillChar : "<br/>"
            } catch (e) {
              range.setStartBefore(child);
              domUtils.remove(child)
            }
          }
        }
        try {
          range.select(true)
        } catch (e) {
        }
      }
      setTimeout(function () {
        range = me.selection.getRange();
        range.scrollToView(me.autoHeightEnabled, me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0);
        me.fireEvent("afterinserthtml", html)
      }, 200)
    }
  };
  UE.plugins["autotypeset"] = function () {
    this.setOpt({
      autotypeset: {
        mergeEmptyline: true,
        removeClass: true,
        removeEmptyline: false,
        textAlign: "left",
        imageBlockLine: "center",
        pasteFilter: false,
        clearFontSize: false,
        clearFontFamily: false,
        removeEmptyNode: false,
        removeTagNames: utils.extend({div: 1}, dtd.$removeEmpty),
        indent: false,
        indentValue: "2em",
        bdc2sb: false,
        tobdc: false
      }
    });
    var me = this, opt = me.options.autotypeset, remainClass = {selectTdClass: 1, pagebreak: 1, anchorclass: 1}, remainTag = {li: 1}, tags = {div: 1, p: 1, blockquote: 1, center: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, span: 1}, highlightCont;
    if (!opt) {
      return
    }
    readLocalOpts();

    function isLine(node, notEmpty) {
      if (!node || node.nodeType == 3) return 0;
      if (domUtils.isBr(node)) return 1;
      if (node && node.parentNode && tags[node.tagName.toLowerCase()]) {
        if (highlightCont && highlightCont.contains(node) || node.getAttribute("pagebreak")) {
          return 0
        }
        return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node, new RegExp("[\\s" + domUtils.fillChar + "]", "g"))
      }
    }

    function removeNotAttributeSpan(node) {
      if (!node.style.cssText) {
        domUtils.removeAttributes(node, ["style"]);
        if (node.tagName.toLowerCase() == "span" && domUtils.hasNoAttributes(node)) {
          domUtils.remove(node, true)
        }
      }
    }

    function autotype(type, html) {
      var me = this, cont;
      if (html) {
        if (!opt.pasteFilter) {
          return
        }
        cont = me.document.createElement("div");
        cont.innerHTML = html.html
      } else {
        cont = me.document.body
      }
      var nodes = domUtils.getElementsByTagName(cont, "*");
      for (var i = 0, ci; ci = nodes[i++];) {
        if (me.fireEvent("excludeNodeinautotype", ci) === true) {
          continue
        }
        if (opt.clearFontSize && ci.style.fontSize) {
          domUtils.removeStyle(ci, "font-size");
          removeNotAttributeSpan(ci)
        }
        if (opt.clearFontFamily && ci.style.fontFamily) {
          domUtils.removeStyle(ci, "font-family");
          removeNotAttributeSpan(ci)
        }
        if (isLine(ci)) {
          if (opt.mergeEmptyline) {
            var next = ci.nextSibling, tmpNode, isBr = domUtils.isBr(ci);
            while (isLine(next)) {
              tmpNode = next;
              next = tmpNode.nextSibling;
              if (isBr && (!next || next && !domUtils.isBr(next))) {
                break
              }
              domUtils.remove(tmpNode)
            }
          }
          if (opt.removeEmptyline && domUtils.inDoc(ci, cont) && !remainTag[ci.parentNode.tagName.toLowerCase()]) {
            if (domUtils.isBr(ci)) {
              next = ci.nextSibling;
              if (next && !domUtils.isBr(next)) {
                continue
              }
            }
            domUtils.remove(ci);
            continue
          }
        }
        if (isLine(ci, true) && ci.tagName != "SPAN") {
          if (opt.indent) {
            ci.style.textIndent = opt.indentValue
          }
          if (opt.textAlign) {
            ci.style.textAlign = opt.textAlign
          }
        }
        if (opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]) {
          if (highlightCont && highlightCont.contains(ci)) {
            continue
          }
          domUtils.removeAttributes(ci, ["class"])
        }
        if (opt.imageBlockLine && ci.tagName.toLowerCase() == "img" && !ci.getAttribute("emotion")) {
          if (html) {
            var img = ci;
            switch (opt.imageBlockLine) {
              case"left":
              case"right":
              case"none":
                var pN = img.parentNode, tmpNode, pre, next;
                while (dtd.$inline[pN.tagName] || pN.tagName == "A") {
                  pN = pN.parentNode
                }
                tmpNode = pN;
                if (tmpNode.tagName == "P" && domUtils.getStyle(tmpNode, "text-align") == "center") {
                  if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) {
                    return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                  }) == 1) {
                    pre = tmpNode.previousSibling;
                    next = tmpNode.nextSibling;
                    if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
                      pre.appendChild(tmpNode.firstChild);
                      while (next.firstChild) {
                        pre.appendChild(next.firstChild)
                      }
                      domUtils.remove(tmpNode);
                      domUtils.remove(next)
                    } else {
                      domUtils.setStyle(tmpNode, "text-align", "")
                    }
                  }
                }
                domUtils.setStyle(img, "float", opt.imageBlockLine);
                break;
              case"center":
                if (me.queryCommandValue("imagefloat") != "center") {
                  pN = img.parentNode;
                  domUtils.setStyle(img, "float", "none");
                  tmpNode = img;
                  while (pN && domUtils.getChildCount(pN, function (node) {
                    return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                  }) == 1 && (dtd.$inline[pN.tagName] || pN.tagName == "A")) {
                    tmpNode = pN;
                    pN = pN.parentNode
                  }
                  var pNode = me.document.createElement("p");
                  domUtils.setAttributes(pNode, {style: "text-align:center"});
                  tmpNode.parentNode.insertBefore(pNode, tmpNode);
                  pNode.appendChild(tmpNode);
                  domUtils.setStyle(tmpNode, "float", "")
                }
            }
          } else {
            var range = me.selection.getRange();
            range.selectNode(ci).select();
            me.execCommand("imagefloat", opt.imageBlockLine)
          }
        }
        if (opt.removeEmptyNode) {
          if (opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci)) {
            domUtils.remove(ci)
          }
        }
      }
      if (opt.tobdc) {
        var root = UE.htmlparser(cont.innerHTML);
        root.traversal(function (node) {
          if (node.type == "text") {
            node.data = ToDBC(node.data)
          }
        });
        cont.innerHTML = root.toHtml()
      }
      if (opt.bdc2sb) {
        var root = UE.htmlparser(cont.innerHTML);
        root.traversal(function (node) {
          if (node.type == "text") {
            node.data = DBC2SB(node.data)
          }
        });
        cont.innerHTML = root.toHtml()
      }
      if (html) {
        html.html = cont.innerHTML
      }
    }

    if (opt.pasteFilter) {
      me.addListener("beforepaste", autotype)
    }

    function DBC2SB(str) {
      var result = "";
      for (var i = 0; i < str.length; i++) {
        var code = str.charCodeAt(i);
        if (code >= 65281 && code <= 65373) {
          result += String.fromCharCode(str.charCodeAt(i) - 65248)
        } else if (code == 12288) {
          result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32)
        } else {
          result += str.charAt(i)
        }
      }
      return result
    }

    function ToDBC(txtstring) {
      txtstring = utils.html(txtstring);
      var tmp = "";
      var mark = "";
      for (var i = 0; i < txtstring.length; i++) {
        if (txtstring.charCodeAt(i) == 32) {
          tmp = tmp + String.fromCharCode(12288)
        } else if (txtstring.charCodeAt(i) < 127) {
          tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248)
        } else {
          tmp += txtstring.charAt(i)
        }
      }
      return tmp
    }

    function readLocalOpts() {
      var cookieOpt = me.getPreferences("autotypeset");
      utils.extend(me.options.autotypeset, cookieOpt)
    }

    me.commands["autotypeset"] = {
      execCommand: function () {
        me.removeListener("beforepaste", autotype);
        if (opt.pasteFilter) {
          me.addListener("beforepaste", autotype)
        }
        autotype.call(me)
      }
    }
  };
  UE.plugin.register("autosubmit", function () {
    return {
      shortcutkey: {autosubmit: "ctrl+13"}, commands: {
        autosubmit: {
          execCommand: function () {
            var me = this, form = domUtils.findParentByTagName(me.iframe, "form", false);
            if (form) {
              if (me.fireEvent("beforesubmit") === false) {
                return
              }
              me.sync();
              form.submit()
            }
          }
        }
      }
    }
  });
  UE.plugin.register("background", function () {
    var me = this, cssRuleId = "editor_background", isSetColored, reg = new RegExp("body[\\s]*\\{(.+)\\}", "i");

    function stringToObj(str) {
      var obj = {}, styles = str.split(";");
      utils.each(styles, function (v) {
        var index = v.indexOf(":"), key = utils.trim(v.substr(0, index)).toLowerCase();
        key && (obj[key] = utils.trim(v.substr(index + 1) || ""))
      });
      return obj
    }

    function setBackground(obj) {
      if (obj) {
        var styles = [];
        for (var name in obj) {
          if (obj.hasOwnProperty(name)) {
            styles.push(name + ":" + obj[name] + "; ")
          }
        }
        utils.cssRule(cssRuleId, styles.length ? "body{" + styles.join("") + "}" : "", me.document)
      } else {
        utils.cssRule(cssRuleId, "", me.document)
      }
    }

    var orgFn = me.hasContents;
    me.hasContents = function () {
      if (me.queryCommandValue("background")) {
        return true
      }
      return orgFn.apply(me, arguments)
    };
    return {
      bindEvents: {
        getAllHtml: function (type, headHtml) {
          var body = this.body, su = domUtils.getComputedStyle(body, "background-image"), url = "";
          if (su.indexOf(me.options.imagePath) > 0) {
            url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/gi, "")
          } else {
            url = su != "none" ? su.replace(/url\("?|"?\)/gi, "") : ""
          }
          var html = '<style type="text/css">body{';
          var bgObj = {
            "background-color": domUtils.getComputedStyle(body, "background-color") || "#ffffff",
            "background-image": url ? "url(" + url + ")" : "",
            "background-repeat": domUtils.getComputedStyle(body, "background-repeat") || "",
            "background-position": browser.ie ? domUtils.getComputedStyle(body, "background-position-x") + " " + domUtils.getComputedStyle(body, "background-position-y") : domUtils.getComputedStyle(body, "background-position"),
            height: domUtils.getComputedStyle(body, "height")
          };
          for (var name in bgObj) {
            if (bgObj.hasOwnProperty(name)) {
              html += name + ":" + bgObj[name] + "; "
            }
          }
          html += "}</style> ";
          headHtml.push(html)
        }, aftersetcontent: function () {
          if (isSetColored == false) setBackground()
        }
      }, inputRule: function (root) {
        isSetColored = false;
        utils.each(root.getNodesByTagName("p"), function (p) {
          var styles = p.getAttr("data-background");
          if (styles) {
            isSetColored = true;
            setBackground(stringToObj(styles));
            p.parentNode.removeChild(p)
          }
        })
      }, outputRule: function (root) {
        var me = this, styles = (utils.cssRule(cssRuleId, me.document) || "").replace(/[\n\r]+/g, "").match(reg);
        if (styles) {
          root.appendChild(UE.uNode.createElement('<p style="display:none;" data-background="' + utils.trim(styles[1].replace(/"/g, "").replace(/[\s]+/g, " ")) + '"><br/></p>'))
        }
      }, commands: {
        background: {
          execCommand: function (cmd, obj) {
            setBackground(obj)
          }, queryCommandValue: function () {
            var me = this, styles = (utils.cssRule(cssRuleId, me.document) || "").replace(/[\n\r]+/g, "").match(reg);
            return styles ? stringToObj(styles[1]) : null
          }, notNeedUndo: true
        }
      }
    }
  });
  UE.commands["imagefloat"] = {
    execCommand: function (cmd, align) {
      var me = this, range = me.selection.getRange();
      if (!range.collapsed) {
        var img = range.getClosedNode();
        if (img && img.tagName === "IMG") {
          switch (align) {
            case"left":
            case"right":
            case"none":
              var pN = img.parentNode, tmpNode, pre, next;
              while (dtd.$inline[pN.tagName] || pN.tagName == "A") {
                pN = pN.parentNode
              }
              tmpNode = pN;
              if (tmpNode.tagName == "P" && domUtils.getStyle(tmpNode, "text-align") == "center") {
                if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function (node) {
                  return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                }) == 1) {
                  pre = tmpNode.previousSibling;
                  next = tmpNode.nextSibling;
                  if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
                    pre.appendChild(tmpNode.firstChild);
                    while (next.firstChild) {
                      pre.appendChild(next.firstChild)
                    }
                    domUtils.remove(tmpNode);
                    domUtils.remove(next)
                  } else {
                    domUtils.setStyle(tmpNode, "text-align", "")
                  }
                }
                range.selectNode(img).select()
              }
              domUtils.setStyle(img, "float", align == "none" ? "" : align);
              if (align == "none") {
                domUtils.removeAttributes(img, "align")
              }
              break;
            case"center":
              if (me.queryCommandValue("imagefloat") != "center") {
                pN = img.parentNode;
                domUtils.setStyle(img, "float", "");
                domUtils.removeAttributes(img, "align");
                tmpNode = img;
                while (pN && domUtils.getChildCount(pN, function (node) {
                  return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                }) == 1 && (dtd.$inline[pN.tagName] || pN.tagName == "A")) {
                  tmpNode = pN;
                  pN = pN.parentNode
                }
                range.setStartBefore(tmpNode).setCursor(false);
                pN = me.document.createElement("div");
                pN.appendChild(tmpNode);
                domUtils.setStyle(tmpNode, "float", "");
                me.execCommand("insertHtml", '<p id="_img_parent_tmp" style="text-align:center">' + pN.innerHTML + "</p>");
                tmpNode = me.document.getElementById("_img_parent_tmp");
                tmpNode.removeAttribute("id");
                tmpNode = tmpNode.firstChild;
                range.selectNode(tmpNode).select();
                next = tmpNode.parentNode.nextSibling;
                if (next && domUtils.isEmptyNode(next)) {
                  domUtils.remove(next)
                }
              }
              break
          }
        }
      }
    }, queryCommandValue: function () {
      var range = this.selection.getRange(), startNode, floatStyle;
      if (range.collapsed) {
        return "none"
      }
      startNode = range.getClosedNode();
      if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") {
        floatStyle = domUtils.getComputedStyle(startNode, "float") || startNode.getAttribute("align");
        if (floatStyle == "none") {
          floatStyle = domUtils.getComputedStyle(startNode.parentNode, "text-align") == "center" ? "center" : floatStyle
        }
        return {left: 1, right: 1, center: 1}[floatStyle] ? floatStyle : "none"
      }
      return "none"
    }, queryCommandState: function () {
      var range = this.selection.getRange(), startNode;
      if (range.collapsed) return -1;
      startNode = range.getClosedNode();
      if (startNode && startNode.nodeType === 1 && startNode.tagName === "IMG") {
        return 0
      }
      return -1
    }
  };
  UE.commands["insertimage"] = {
    execCommand: function (cmd, opt) {
      opt = utils.isArray(opt) ? opt : [opt];
      if (!opt.length) {
        return
      }
      var me = this, range = me.selection.getRange(), img = range.getClosedNode();
      if (me.fireEvent("beforeinsertimage", opt) === true) {
        return
      }
      if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1) && !img.getAttribute("data-word-image")) {
        var first = opt.shift();
        var floatStyle = first["floatStyle"];
        delete first["floatStyle"];
        domUtils.setAttributes(img, first);
        me.execCommand("imagefloat", floatStyle);
        if (opt.length > 0) {
          range.setStartAfter(img).setCursor(false, true);
          me.execCommand("insertimage", opt)
        }
      } else {
        var html = [], str = "", ci;
        ci = opt[0];
        if (opt.length == 1) {
          str = '<img src="' + ci.src + '" ' + (ci._src ? ' _src="' + ci._src + '" ' : "") + (ci.width ? 'width="' + ci.width + '" ' : "") + (ci.height ? ' height="' + ci.height + '" ' : "") + (ci["floatStyle"] == "left" || ci["floatStyle"] == "right" ? ' style="float:' + ci["floatStyle"] + ';"' : "") + (ci.title && ci.title != "" ? ' title="' + ci.title + '"' : "") + (ci.border && ci.border != "0" ? ' border="' + ci.border + '"' : "") + (ci.alt && ci.alt != "" ? ' alt="' + ci.alt + '"' : "") + (ci.hspace && ci.hspace != "0" ? ' hspace = "' + ci.hspace + '"' : "") + (ci.vspace && ci.vspace != "0" ? ' vspace = "' + ci.vspace + '"' : "") + "/>";
          if (ci["floatStyle"] == "center") {
            str = '<p style="text-align: center">' + str + "</p>"
          }
          html.push(str)
        } else {
          for (var i = 0; ci = opt[i++];) {
            str = "<p " + (ci["floatStyle"] == "center" ? 'style="text-align: center" ' : "") + '><img src="' + ci.src + '" ' + (ci.width ? 'width="' + ci.width + '" ' : "") + (ci._src ? ' _src="' + ci._src + '" ' : "") + (ci.height ? ' height="' + ci.height + '" ' : "") + ' style="' + (ci["floatStyle"] && ci["floatStyle"] != "center" ? "float:" + ci["floatStyle"] + ";" : "") + (ci.border || "") + '" ' + (ci.title ? ' title="' + ci.title + '"' : "") + " /></p>";
            html.push(str)
          }
        }
        me.execCommand("insertHtml", html.join(""))
      }
      me.fireEvent("afterinsertimage", opt)
    }
  };
  UE.plugins["justify"] = function () {
    var me = this, block = domUtils.isBlockElm, defaultValue = {left: 1, right: 1, center: 1, justify: 1}, doJustify = function (range, style) {
      var bookmark = range.createBookmark(), filterFn = function (node) {
        return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node)
      };
      range.enlarge(true);
      var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode;
      while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
        if (current.nodeType == 3 || !block(current)) {
          tmpRange.setStartBefore(current);
          while (current && current !== bookmark2.end && !block(current)) {
            tmpNode = current;
            current = domUtils.getNextDomNode(current, false, null, function (node) {
              return !block(node)
            })
          }
          tmpRange.setEndAfter(tmpNode);
          var common = tmpRange.getCommonAncestor();
          if (!domUtils.isBody(common) && block(common)) {
            domUtils.setStyles(common, utils.isString(style) ? {"text-align": style} : style);
            current = common
          } else {
            var p = range.document.createElement("p");
            domUtils.setStyles(p, utils.isString(style) ? {"text-align": style} : style);
            var frag = tmpRange.extractContents();
            p.appendChild(frag);
            tmpRange.insertNode(p);
            current = p
          }
          current = domUtils.getNextDomNode(current, false, filterFn)
        } else {
          current = domUtils.getNextDomNode(current, true, filterFn)
        }
      }
      return range.moveToBookmark(bookmark2).moveToBookmark(bookmark)
    };
    UE.commands["justify"] = {
      execCommand: function (cmdName, align) {
        var range = this.selection.getRange(), txt;
        if (range.collapsed) {
          txt = this.document.createTextNode("p");
          range.insertNode(txt)
        }
        doJustify(range, align);
        if (txt) {
          range.setStartBefore(txt).collapse(true);
          domUtils.remove(txt)
        }
        range.select();
        return true
      }, queryCommandValue: function () {
        var startNode = this.selection.getStart(), value = domUtils.getComputedStyle(startNode, "text-align");
        return defaultValue[value] ? value : "left"
      }, queryCommandState: function () {
        var start = this.selection.getStart(), cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
        return cell ? -1 : 0
      }
    }
  };
  UE.plugins["font"] = function () {
    var me = this, fonts = {forecolor: "color", backcolor: "background-color", fontsize: "font-size", fontfamily: "font-family", underline: "text-decoration", strikethrough: "text-decoration", fontborder: "border"}, lang = me.getLang(),
      needCmd = {underline: 1, strikethrough: 1, fontborder: 1}, needSetChild = {forecolor: "color", backcolor: "background-color", fontsize: "font-size", fontfamily: "font-family"};
    me.setOpt({
      fontfamily: [{name: "default", val: "default"}, {name: "songti", val: "宋体,SimSun"}, {name: "yahei", val: "微软雅黑,Microsoft YaHei"}, {name: "kaiti", val: "楷体,楷体_GB2312,SimKai"}, {
        name: "heiti",
        val: "黑体,SimHei"
      }, {name: "lishu", val: "隶书,SimLi"}, {name: "arial", val: "arial,helvetica,sans-serif"}, {name: "timesNewRoman", val: "times new roman"}], fontsize: [10, 11, 12, 14, 16, 18, 20, 24, 36]
    });

    function mergeWithParent(node) {
      var parent;
      while (parent = node.parentNode) {
        if (parent.tagName == "SPAN" && domUtils.getChildCount(parent, function (child) {
          return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child)
        }) == 1) {
          parent.style.cssText += node.style.cssText;
          domUtils.remove(node, true);
          node = parent
        } else {
          break
        }
      }
    }

    function mergeChild(rng, cmdName, value) {
      if (needSetChild[cmdName]) {
        rng.adjustmentBoundary();
        if (!rng.collapsed && rng.startContainer.nodeType == 1) {
          var start = rng.startContainer.childNodes[rng.startOffset];
          if (start && domUtils.isTagNode(start, "span")) {
            var bk = rng.createBookmark();
            utils.each(domUtils.getElementsByTagName(start, "span"), function (span) {
              if (!span.parentNode || domUtils.isBookmarkNode(span)) return;
              if (cmdName == "backcolor" && domUtils.getComputedStyle(span, "background-color").toLowerCase() === value) {
                return
              }
              domUtils.removeStyle(span, needSetChild[cmdName]);
              if (span.style.cssText.replace(/^\s+$/, "").length == 0) {
                domUtils.remove(span, true)
              }
            });
            rng.moveToBookmark(bk)
          }
        }
      }
    }

    function mergesibling(rng, cmdName, value) {
      var collapsed = rng.collapsed, bk = rng.createBookmark(), common;
      if (collapsed) {
        common = bk.start.parentNode;
        while (dtd.$inline[common.tagName]) {
          common = common.parentNode
        }
      } else {
        common = domUtils.getCommonAncestor(bk.start, bk.end)
      }
      utils.each(domUtils.getElementsByTagName(common, "span"), function (span) {
        if (!span.parentNode || domUtils.isBookmarkNode(span)) return;
        if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) {
          if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) {
            domUtils.remove(span, true)
          } else {
            domUtils.removeStyle(span, "border")
          }
          return
        }
        if (/border/i.test(span.style.cssText) && span.parentNode.tagName == "SPAN" && /border/i.test(span.parentNode.style.cssText)) {
          span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, "")
        }
        if (!(cmdName == "fontborder" && value == "none")) {
          var next = span.nextSibling;
          while (next && next.nodeType == 1 && next.tagName == "SPAN") {
            if (domUtils.isBookmarkNode(next) && cmdName == "fontborder") {
              span.appendChild(next);
              next = span.nextSibling;
              continue
            }
            if (next.style.cssText == span.style.cssText) {
              domUtils.moveChild(next, span);
              domUtils.remove(next)
            }
            if (span.nextSibling === next) break;
            next = span.nextSibling
          }
        }
        mergeWithParent(span);
        if (browser.ie && browser.version > 8) {
          var parent = domUtils.findParent(span, function (n) {
            return n.tagName == "SPAN" && /background-color/.test(n.style.cssText)
          });
          if (parent && !/background-color/.test(span.style.cssText)) {
            span.style.backgroundColor = parent.style.backgroundColor
          }
        }
      });
      rng.moveToBookmark(bk);
      mergeChild(rng, cmdName, value)
    }

    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName("u s del font strike"), function (node) {
        if (node.tagName == "font") {
          var cssStyle = [];
          for (var p in node.attrs) {
            switch (p) {
              case"size":
                cssStyle.push("font-size:" + ({1: "10", 2: "12", 3: "16", 4: "18", 5: "24", 6: "32", 7: "48"}[node.attrs[p]] || node.attrs[p]) + "px");
                break;
              case"color":
                cssStyle.push("color:" + node.attrs[p]);
                break;
              case"face":
                cssStyle.push("font-family:" + node.attrs[p]);
                break;
              case"style":
                cssStyle.push(node.attrs[p])
            }
          }
          node.attrs = {style: cssStyle.join(";")}
        } else {
          var val = node.tagName == "u" ? "underline" : "line-through";
          node.attrs = {style: (node.getAttr("style") || "") + "text-decoration:" + val + ";"}
        }
        node.tagName = "span"
      })
    });
    for (var p in fonts) {
      (function (cmd, style) {
        UE.commands[cmd] = {
          execCommand: function (cmdName, value) {
            value = value || (this.queryCommandState(cmdName) ? "none" : cmdName === "underline" ? "underline" : cmdName === "fontborder" ? "1px solid #000" : "line-through");
            var me = this, range = this.selection.getRange(), text;
            if (value === "default") {
              if (range.collapsed) {
                text = me.document.createTextNode("font");
                range.insertNode(text).select()
              }
              me.execCommand("removeFormat", "span,a", style);
              if (text) {
                range.setStartBefore(text).collapse(true);
                domUtils.remove(text)
              }
              mergesibling(range, cmdName, value);
              range.select()
            } else {
              if (!range.collapsed) {
                if (needCmd[cmd] && me.queryCommandValue(cmd)) {
                  me.execCommand("removeFormat", "span,a", style)
                }
                range = me.selection.getRange();
                range.applyInlineStyle("span", {style: style + ":" + value});
                mergesibling(range, cmdName, value);
                range.select()
              } else {
                var span = domUtils.findParentByTagName(range.startContainer, "span", true);
                text = me.document.createTextNode("font");
                if (span && !span.children.length && !span[browser.ie ? "innerText" : "textContent"].replace(fillCharReg, "").length) {
                  range.insertNode(text);
                  if (needCmd[cmd]) {
                    range.selectNode(text).select();
                    me.execCommand("removeFormat", "span,a", style, null);
                    span = domUtils.findParentByTagName(text, "span", true);
                    range.setStartBefore(text)
                  }
                  span && (span.style.cssText += ";" + style + ":" + value);
                  range.collapse(true).select()
                } else {
                  range.insertNode(text);
                  range.selectNode(text).select();
                  span = range.document.createElement("span");
                  if (needCmd[cmd]) {
                    if (domUtils.findParentByTagName(text, "a", true)) {
                      range.setStartBefore(text).setCursor();
                      domUtils.remove(text);
                      return
                    }
                    me.execCommand("removeFormat", "span,a", style)
                  }
                  span.style.cssText = style + ":" + value;
                  text.parentNode.insertBefore(span, text);
                  if (!browser.ie || browser.ie && browser.version === 9) {
                    var spanParent = span.parentNode;
                    while (!domUtils.isBlockElm(spanParent)) {
                      if (spanParent.tagName === "SPAN") {
                        span.style.cssText = spanParent.style.cssText + ";" + span.style.cssText
                      }
                      spanParent = spanParent.parentNode
                    }
                  }
                  if (opera) {
                    setTimeout(function () {
                      range.setStart(span, 0).collapse(true);
                      mergesibling(range, cmdName, value);
                      range.select()
                    })
                  } else {
                    range.setStart(span, 0).collapse(true);
                    mergesibling(range, cmdName, value);
                    range.select()
                  }
                }
                domUtils.remove(text)
              }
            }
            return true
          }, queryCommandValue: function (cmdName) {
            var startNode = this.selection.getStart();
            var styleVal;
            if (cmdName === "underline" || cmdName === "strikethrough") {
              var tmpNode = startNode, value;
              while (tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)) {
                if (tmpNode.nodeType === 1) {
                  value = domUtils.getComputedStyle(tmpNode, style);
                  if (value !== "none") {
                    return value
                  }
                }
                tmpNode = tmpNode.parentNode
              }
              return "none"
            } else if (cmdName === "fontborder") {
              var tmp = startNode, val;
              while (tmp && dtd.$inline[tmp.tagName]) {
                if (val = domUtils.getComputedStyle(tmp, "border")) {
                  if (/1px/.test(val) && /solid/.test(val)) {
                    return val
                  }
                }
                tmp = tmp.parentNode
              }
              return ""
            } else if (cmdName === "FontSize") {
              styleVal = domUtils.getComputedStyle(startNode, style);
              tmp = /^([\d\.]+)(\w+)$/.exec(styleVal);
              if (tmp) {
                return Math.floor(tmp[1]) + tmp[2]
              }
              return styleVal
            } else if (cmdName === "FontFamily") {
              styleVal = domUtils.getComputedStyle(startNode, style);
              styleVal = styleVal.replace(/['"]/g, "");
              styleVal = styleVal.replace(/\s*,\s*/g, ",");
              var fontFamily = lang.fontfamily.default;
              var fontList = me.options["fontfamily"] || [];
              for (var i = 0; i < fontList.length; i++) {
                var v = fontList[i];
                if (v.val === styleVal) {
                  fontFamily = styleVal;
                  break
                }
              }
              return fontFamily
            }
            value = domUtils.getComputedStyle(startNode, style);
            return value
          }, queryCommandState: function (cmdName) {
            if (!needCmd[cmdName]) return 0;
            var val = this.queryCommandValue(cmdName);
            if (cmdName === "fontborder") {
              return /1px/.test(val) && /solid/.test(val)
            } else {
              return cmdName === "underline" ? /underline/.test(val) : /line\-through/.test(val)
            }
          }
        }
      })(p, fonts[p])
    }
  };
  UE.plugins["link"] = function () {
    function optimize(range) {
      var start = range.startContainer, end = range.endContainer;
      if (start = domUtils.findParentByTagName(start, "a", true)) {
        range.setStartBefore(start)
      }
      if (end = domUtils.findParentByTagName(end, "a", true)) {
        range.setEndAfter(end)
      }
    }

    UE.commands["unlink"] = {
      execCommand: function () {
        var range = this.selection.getRange(), bookmark;
        if (range.collapsed && !domUtils.findParentByTagName(range.startContainer, "a", true)) {
          return
        }
        bookmark = range.createBookmark();
        optimize(range);
        range.removeInlineStyle("a").moveToBookmark(bookmark).select()
      }, queryCommandState: function () {
        return !this.highlight && this.queryCommandValue("link") ? 0 : -1
      }
    };

    function doLink(range, opt, me) {
      var rngClone = range.cloneRange(), link = me.queryCommandValue("link");
      optimize(range = range.adjustmentBoundary());
      var start = range.startContainer;
      if (start.nodeType == 1 && link) {
        start = start.childNodes[range.startOffset];
        if (start && start.nodeType == 1 && start.tagName == "A" && /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[browser.ie ? "innerText" : "textContent"])) {
          start[browser.ie ? "innerText" : "textContent"] = utils.html(opt.textValue || opt.href)
        }
      }
      if (!rngClone.collapsed || link) {
        range.removeInlineStyle("a");
        rngClone = range.cloneRange()
      }
      if (rngClone.collapsed) {
        var a = range.document.createElement("a"), text = "";
        if (opt.textValue) {
          text = utils.html(opt.textValue);
          delete opt.textValue
        } else {
          text = utils.html(opt.href)
        }
        domUtils.setAttributes(a, opt);
        start = domUtils.findParentByTagName(rngClone.startContainer, "a", true);
        if (start && domUtils.isInNodeEndBoundary(rngClone, start)) {
          range.setStartAfter(start).collapse(true)
        }
        a[browser.ie ? "innerText" : "textContent"] = text;
        range.insertNode(a).selectNode(a)
      } else {
        range.applyInlineStyle("a", opt)
      }
    }

    UE.commands["link"] = {
      execCommand: function (cmdName, opt) {
        var range;
        opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g));
        opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g));
        opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g));
        doLink(range = this.selection.getRange(), opt, this);
        range.collapse().select(true)
      }, queryCommandValue: function () {
        var range = this.selection.getRange(), node;
        if (range.collapsed) {
          node = range.startContainer;
          node = node.nodeType == 1 ? node : node.parentNode;
          if (node && (node = domUtils.findParentByTagName(node, "a", true)) && !domUtils.isInNodeEndBoundary(range, node)) {
            return node
          }
        } else {
          range.shrinkBoundary();
          var start = range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset] ? range.startContainer : range.startContainer.childNodes[range.startOffset],
            end = range.endContainer.nodeType == 3 || range.endOffset == 0 ? range.endContainer : range.endContainer.childNodes[range.endOffset - 1], common = range.getCommonAncestor();
          node = domUtils.findParentByTagName(common, "a", true);
          if (!node && common.nodeType == 1) {
            var as = common.getElementsByTagName("a"), ps, pe;
            for (var i = 0, ci; ci = as[i++];) {
              ps = domUtils.getPosition(ci, start), pe = domUtils.getPosition(ci, end);
              if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) && (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)) {
                node = ci;
                break
              }
            }
          }
          return node
        }
      }, queryCommandState: function () {
        var img = this.selection.getRange().getClosedNode(), flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1);
        return flag ? -1 : 0
      }
    }
  };
  UE.plugins["insertframe"] = function () {
    var me = this;

    function deleteIframe() {
      me._iframe && delete me._iframe
    }

    me.addListener("selectionchange", function () {
      deleteIframe()
    })
  };
  UE.commands["scrawl"] = {
    queryCommandState: function () {
      return browser.ie && browser.version <= 8 ? -1 : 0
    }
  };
  UE.plugins["removeformat"] = function () {
    var me = this;
    me.setOpt({removeFormatTags: "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var", removeFormatAttributes: "class,style,lang,width,height,align,hspace,valign"});
    me.commands["removeformat"] = {
      execCommand: function (cmdName, tags, style, attrs, notIncludeA) {
        var tagReg = new RegExp("^(?:" + (tags || this.options.removeFormatTags).replace(/,/g, "|") + ")$", "i"), removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split(","), range = new dom.Range(this.document),
          bookmark, node, parent, filter = function (node) {
            return node.nodeType == 1
          };

        function isRedundantSpan(node) {
          if (node.nodeType == 3 || node.tagName.toLowerCase() != "span") {
            return 0
          }
          if (browser.ie) {
            var attrs = node.attributes;
            if (attrs.length) {
              for (var i = 0, l = attrs.length; i < l; i++) {
                if (attrs[i].specified) {
                  return 0
                }
              }
              return 1
            }
          }
          return !node.attributes.length
        }

        function doRemove(range) {
          var bookmark1 = range.createBookmark();
          if (range.collapsed) {
            range.enlarge(true)
          }
          if (!notIncludeA) {
            var aNode = domUtils.findParentByTagName(range.startContainer, "a", true);
            if (aNode) {
              range.setStartBefore(aNode)
            }
            aNode = domUtils.findParentByTagName(range.endContainer, "a", true);
            if (aNode) {
              range.setEndAfter(aNode)
            }
          }
          bookmark = range.createBookmark();
          node = bookmark.start;
          while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
            domUtils.breakParent(node, parent);
            domUtils.clearEmptySibling(node)
          }
          if (bookmark.end) {
            node = bookmark.end;
            while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
              domUtils.breakParent(node, parent);
              domUtils.clearEmptySibling(node)
            }
            var current = domUtils.getNextDomNode(bookmark.start, false, filter), next;
            while (current) {
              if (current == bookmark.end) {
                break
              }
              next = domUtils.getNextDomNode(current, true, filter);
              if (!dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode(current)) {
                if (tagReg.test(current.tagName)) {
                  if (style) {
                    domUtils.removeStyle(current, style);
                    if (isRedundantSpan(current) && style != "text-decoration") {
                      domUtils.remove(current, true)
                    }
                  } else {
                    domUtils.remove(current, true)
                  }
                } else {
                  if (true) {
                    domUtils.removeAttributes(current, removeFormatAttributes);
                    if (isRedundantSpan(current)) {
                      domUtils.remove(current, true)
                    }
                  } else {
                  }
                }
              }
              current = next
            }
          }
          var pN = bookmark.start.parentNode;
          if (domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
            domUtils.removeAttributes(pN, removeFormatAttributes)
          }
          pN = bookmark.end.parentNode;
          if (bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
            domUtils.removeAttributes(pN, removeFormatAttributes)
          }
          range.moveToBookmark(bookmark).moveToBookmark(bookmark1);
          var node = range.startContainer, tmp, collapsed = range.collapsed;
          while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
            tmp = node.parentNode;
            range.setStartBefore(node);
            if (range.startContainer === range.endContainer) {
              range.endOffset--
            }
            domUtils.remove(node);
            node = tmp
          }
          if (!collapsed) {
            node = range.endContainer;
            while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
              tmp = node.parentNode;
              range.setEndBefore(node);
              domUtils.remove(node);
              node = tmp
            }
          }
        }

        range = this.selection.getRange();
        doRemove(range);
        range.select()
      }
    }
  };
  UE.plugins["blockquote"] = function () {
    var me = this;

    function getObj(editor) {
      return domUtils.filterNodeList(editor.selection.getStartElementPath(), "blockquote")
    }

    me.commands["blockquote"] = {
      execCommand: function (cmdName, attrs) {
        var range = this.selection.getRange(), obj = getObj(this), blockquote = dtd.blockquote, bookmark = range.createBookmark();
        if (obj) {
          var start = range.startContainer, startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start, function (node) {
            return domUtils.isBlockElm(node)
          }), end = range.endContainer, endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end, function (node) {
            return domUtils.isBlockElm(node)
          });
          startBlock = domUtils.findParentByTagName(startBlock, "li", true) || startBlock;
          endBlock = domUtils.findParentByTagName(endBlock, "li", true) || endBlock;
          if (startBlock.tagName == "LI" || startBlock.tagName == "TD" || startBlock === obj || domUtils.isBody(startBlock)) {
            domUtils.remove(obj, true)
          } else {
            domUtils.breakParent(startBlock, obj)
          }
          if (startBlock !== endBlock) {
            obj = domUtils.findParentByTagName(endBlock, "blockquote");
            if (obj) {
              if (endBlock.tagName == "LI" || endBlock.tagName == "TD" || domUtils.isBody(endBlock)) {
                obj.parentNode && domUtils.remove(obj, true)
              } else {
                domUtils.breakParent(endBlock, obj)
              }
            }
          }
          var blockquotes = domUtils.getElementsByTagName(this.document, "blockquote");
          for (var i = 0, bi; bi = blockquotes[i++];) {
            if (!bi.childNodes.length) {
              domUtils.remove(bi)
            } else if (domUtils.getPosition(bi, startBlock) & domUtils.POSITION_FOLLOWING && domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING) {
              domUtils.remove(bi, true)
            }
          }
        } else {
          var tmpRange = range.cloneRange(), node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode, preNode = node, doEnd = 1;
          while (1) {
            if (domUtils.isBody(node)) {
              if (preNode !== node) {
                if (range.collapsed) {
                  tmpRange.selectNode(preNode);
                  doEnd = 0
                } else {
                  tmpRange.setStartBefore(preNode)
                }
              } else {
                tmpRange.setStart(node, 0)
              }
              break
            }
            if (!blockquote[node.tagName]) {
              if (range.collapsed) {
                tmpRange.selectNode(preNode)
              } else {
                tmpRange.setStartBefore(preNode)
              }
              break
            }
            preNode = node;
            node = node.parentNode
          }
          if (doEnd) {
            preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode;
            while (1) {
              if (domUtils.isBody(node)) {
                if (preNode !== node) {
                  tmpRange.setEndAfter(preNode)
                } else {
                  tmpRange.setEnd(node, node.childNodes.length)
                }
                break
              }
              if (!blockquote[node.tagName]) {
                tmpRange.setEndAfter(preNode);
                break
              }
              preNode = node;
              node = node.parentNode
            }
          }
          node = range.document.createElement("blockquote");
          domUtils.setAttributes(node, attrs);
          node.appendChild(tmpRange.extractContents());
          tmpRange.insertNode(node);
          var childs = domUtils.getElementsByTagName(node, "blockquote");
          for (var i = 0, ci; ci = childs[i++];) {
            if (ci.parentNode) {
              domUtils.remove(ci, true)
            }
          }
        }
        range.moveToBookmark(bookmark).select()
      }, queryCommandState: function () {
        return getObj(this) ? 1 : 0
      }
    }
  };
  UE.commands["touppercase"] = UE.commands["tolowercase"] = {
    execCommand: function (cmd) {
      var me = this;
      var rng = me.selection.getRange();
      if (rng.collapsed) {
        return rng
      }
      var bk = rng.createBookmark(), bkEnd = bk.end, filterFn = function (node) {
        return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
      }, curNode = domUtils.getNextDomNode(bk.start, false, filterFn);
      while (curNode && domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING) {
        if (curNode.nodeType == 3) {
          curNode.nodeValue = curNode.nodeValue[cmd == "touppercase" ? "toUpperCase" : "toLowerCase"]()
        }
        curNode = domUtils.getNextDomNode(curNode, true, filterFn);
        if (curNode === bkEnd) {
          break
        }
      }
      rng.moveToBookmark(bk).select()
    }
  };
  UE.commands["indent"] = {
    execCommand: function () {
      var me = this, value = me.queryCommandState("indent") ? "0em" : me.options.indentValue || "2em";
      me.execCommand("Paragraph", "p", {style: "text-indent:" + value})
    }, queryCommandState: function () {
      var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), "p h1 h2 h3 h4 h5 h6");
      return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0
    }
  };
  UE.commands["print"] = {
    execCommand: function () {
      this.window.print()
    }, notNeedUndo: 1
  };
  UE.commands["preview"] = {
    execCommand: function () {
      var w = window.open("", "_blank", ""), d = w.document;
      d.open();
      d.write('<!DOCTYPE html><html><head><meta charset="utf-8"/><script src="' + this.options.UEDITOR_HOME_URL + 'ueditor.parse.js"><\/script><script>' + "setTimeout(function(){uParse('div',{rootPath: '" + this.options.UEDITOR_HOME_URL + "'})},300)" + "<\/script></head><body><div>" + this.getContent(null, null, true) + "</div></body></html>");
      d.close()
    }, notNeedUndo: 1
  };
  UE.plugins["selectall"] = function () {
    var me = this;
    me.commands["selectall"] = {
      execCommand: function () {
        var me = this, body = me.body, range = me.selection.getRange();
        range.selectNodeContents(body);
        if (domUtils.isEmptyBlock(body)) {
          if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) {
            range.setStartAtFirst(body.firstChild)
          }
          range.collapse(true)
        }
        range.select(true)
      }, notNeedUndo: 1
    };
    me.addshortcutkey({selectAll: "ctrl+65"})
  };
  UE.plugins["paragraph"] = function () {
    var me = this, block = domUtils.isBlockElm, notExchange = ["TD", "LI", "PRE"], doParagraph = function (range, style, attrs, sourceCmdName) {
      var bookmark = range.createBookmark(), filterFn = function (node) {
        return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node)
      }, para;
      range.enlarge(true);
      var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode;
      while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
        if (current.nodeType === 3 || !block(current)) {
          tmpRange.setStartBefore(current);
          while (current && current !== bookmark2.end && !block(current)) {
            tmpNode = current;
            current = domUtils.getNextDomNode(current, false, null, function (node) {
              return !block(node)
            })
          }
          tmpRange.setEndAfter(tmpNode);
          para = range.document.createElement(style);
          if (attrs) {
            domUtils.setAttributes(para, attrs);
            if (sourceCmdName && sourceCmdName === "customstyle" && attrs.style) {
              para.style.cssText = attrs.style
            }
          }
          para.appendChild(tmpRange.extractContents());
          if (domUtils.isEmptyNode(para)) {
            domUtils.fillChar(range.document, para)
          }
          tmpRange.insertNode(para);
          var parent = para.parentNode;
          if (block(parent) && !domUtils.isBody(para.parentNode) && utils.indexOf(notExchange, parent.tagName) === -1) {
            if (!(sourceCmdName && sourceCmdName === "customstyle")) {
              parent.getAttribute("dir") && para.setAttribute("dir", parent.getAttribute("dir"));
              parent.style.cssText && (para.style.cssText = parent.style.cssText + ";" + para.style.cssText);
              parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign);
              parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent);
              parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding)
            }
            if (attrs && /h\d/i.test(parent.tagName) && !/h\d/i.test(para.tagName)) {
              domUtils.setAttributes(parent, attrs);
              if (sourceCmdName && sourceCmdName === "customstyle" && attrs.style) {
                parent.style.cssText = attrs.style
              }
              domUtils.remove(para.parentNode, true);
              para = parent
            } else {
              domUtils.remove(para.parentNode, true)
            }
          }
          if (utils.indexOf(notExchange, parent.tagName) !== -1) {
            current = parent
          } else {
            current = para
          }
          current = domUtils.getNextDomNode(current, false, filterFn)
        } else {
          current = domUtils.getNextDomNode(current, true, filterFn)
        }
      }
      return range.moveToBookmark(bookmark2).moveToBookmark(bookmark)
    };
    me.setOpt("paragraph", {p: "", h1: "", h2: "", h3: "", h4: "", h5: "", h6: ""});
    me.commands["paragraph"] = {
      execCommand: function (cmdName, style, attrs, sourceCmdName) {
        var range = this.selection.getRange();
        if (range.collapsed) {
          var txt = this.document.createTextNode("p");
          range.insertNode(txt);
          if (browser.ie) {
            var node = txt.previousSibling;
            if (node && domUtils.isWhitespace(node)) {
              domUtils.remove(node)
            }
            node = txt.nextSibling;
            if (node && domUtils.isWhitespace(node)) {
              domUtils.remove(node)
            }
          }
        }
        range = doParagraph(range, style, attrs, sourceCmdName);
        if (txt) {
          range.setStartBefore(txt).collapse(true);
          pN = txt.parentNode;
          domUtils.remove(txt);
          if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) {
            domUtils.fillNode(this.document, pN)
          }
        }
        if (browser.gecko && range.collapsed && range.startContainer.nodeType === 1) {
          var child = range.startContainer.childNodes[range.startOffset];
          if (child && child.nodeType === 1 && child.tagName.toLowerCase() === style) {
            range.setStart(child, 0).collapse(true)
          }
        }
        range.select();
        return true
      }, queryCommandValue: function () {
        var node = domUtils.filterNodeList(this.selection.getStartElementPath(), "p h1 h2 h3 h4 h5 h6");
        return node ? node.tagName.toLowerCase() : ""
      }
    }
  };
  (function () {
    var block = domUtils.isBlockElm, getObj = function (editor) {
      return domUtils.filterNodeList(editor.selection.getStartElementPath(), function (n) {
        return n && n.nodeType == 1 && n.getAttribute("dir")
      })
    }, doDirectionality = function (range, editor, forward) {
      var bookmark, filterFn = function (node) {
        return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node)
      }, obj = getObj(editor);
      if (obj && range.collapsed) {
        obj.setAttribute("dir", forward);
        return range
      }
      bookmark = range.createBookmark();
      range.enlarge(true);
      var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode;
      while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
        if (current.nodeType == 3 || !block(current)) {
          tmpRange.setStartBefore(current);
          while (current && current !== bookmark2.end && !block(current)) {
            tmpNode = current;
            current = domUtils.getNextDomNode(current, false, null, function (node) {
              return !block(node)
            })
          }
          tmpRange.setEndAfter(tmpNode);
          var common = tmpRange.getCommonAncestor();
          if (!domUtils.isBody(common) && block(common)) {
            common.setAttribute("dir", forward);
            current = common
          } else {
            var p = range.document.createElement("p");
            p.setAttribute("dir", forward);
            var frag = tmpRange.extractContents();
            p.appendChild(frag);
            tmpRange.insertNode(p);
            current = p
          }
          current = domUtils.getNextDomNode(current, false, filterFn)
        } else {
          current = domUtils.getNextDomNode(current, true, filterFn)
        }
      }
      return range.moveToBookmark(bookmark2).moveToBookmark(bookmark)
    };
    UE.commands["directionality"] = {
      execCommand: function (cmdName, forward) {
        var range = this.selection.getRange();
        if (range.collapsed) {
          var txt = this.document.createTextNode("d");
          range.insertNode(txt)
        }
        doDirectionality(range, this, forward);
        if (txt) {
          range.setStartBefore(txt).collapse(true);
          domUtils.remove(txt)
        }
        range.select();
        return true
      }, queryCommandValue: function () {
        var node = getObj(this);
        return node ? node.getAttribute("dir") : "ltr"
      }
    }
  })();
  UE.plugins["horizontal"] = function () {
    var me = this;
    me.commands["horizontal"] = {
      execCommand: function (cmdName) {
        var me = this;
        if (me.queryCommandState(cmdName) !== -1) {
          me.execCommand("insertHtml", "<hr>");
          var range = me.selection.getRange(), start = range.startContainer;
          if (start.nodeType == 1 && !start.childNodes[range.startOffset]) {
            var tmp;
            if (tmp = start.childNodes[range.startOffset - 1]) {
              if (tmp.nodeType == 1 && tmp.tagName == "HR") {
                if (me.options.enterTag == "p") {
                  tmp = me.document.createElement("p");
                  range.insertNode(tmp);
                  range.setStart(tmp, 0).setCursor()
                } else {
                  tmp = me.document.createElement("br");
                  range.insertNode(tmp);
                  range.setStartBefore(tmp).setCursor()
                }
              }
            }
          }
          return true
        }
      }, queryCommandState: function () {
        return domUtils.filterNodeList(this.selection.getStartElementPath(), "table") ? -1 : 0
      }
    };
    me.addListener("delkeydown", function (name, evt) {
      var rng = this.selection.getRange();
      rng.txtToElmBoundary(true);
      if (domUtils.isStartInblock(rng)) {
        var tmpNode = rng.startContainer;
        var pre = tmpNode.previousSibling;
        if (pre && domUtils.isTagNode(pre, "hr")) {
          domUtils.remove(pre);
          rng.select();
          domUtils.preventDefault(evt);
          return true
        }
      }
    })
  };
  UE.commands["time"] = UE.commands["date"] = {
    execCommand: function (cmd, format) {
      var date = new Date;

      function formatTime(date, format) {
        var hh = ("0" + date.getHours()).slice(-2), ii = ("0" + date.getMinutes()).slice(-2), ss = ("0" + date.getSeconds()).slice(-2);
        format = format || "hh:ii:ss";
        return format.replace(/hh/gi, hh).replace(/ii/gi, ii).replace(/ss/gi, ss)
      }

      function formatDate(date, format) {
        var yyyy = ("000" + date.getFullYear()).slice(-4), yy = yyyy.slice(-2), mm = ("0" + (date.getMonth() + 1)).slice(-2), dd = ("0" + date.getDate()).slice(-2);
        format = format || "yyyy-mm-dd";
        return format.replace(/yyyy/gi, yyyy).replace(/yy/gi, yy).replace(/mm/gi, mm).replace(/dd/gi, dd)
      }

      this.execCommand("insertHtml", cmd == "time" ? formatTime(date, format) : formatDate(date, format))
    }
  };
  UE.plugins["rowspacing"] = function () {
    var me = this;
    me.setOpt({rowspacingtop: ["5", "10", "15", "20", "25"], rowspacingbottom: ["5", "10", "15", "20", "25"]});
    me.commands["rowspacing"] = {
      execCommand: function (cmdName, value, dir) {
        this.execCommand("paragraph", "p", {style: "margin-" + dir + ":" + value + "px"});
        return true
      }, queryCommandValue: function (cmdName, dir) {
        var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) {
          return domUtils.isBlockElm(node)
        }), value;
        if (pN) {
          value = domUtils.getComputedStyle(pN, "margin-" + dir).replace(/[^\d]/g, "");
          return !value ? 0 : value
        }
        return 0
      }
    }
  };
  UE.plugins["lineheight"] = function () {
    var me = this;
    me.setOpt({lineheight: ["1", "1.5", "1.75", "2", "3", "4", "5"]});
    me.commands["lineheight"] = {
      execCommand: function (cmdName, value) {
        this.execCommand("paragraph", "p", {style: "line-height:" + (value == "1" ? "normal" : value + "em")});
        return true
      }, queryCommandValue: function () {
        var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) {
          return domUtils.isBlockElm(node)
        });
        if (pN) {
          var value = domUtils.getComputedStyle(pN, "line-height");
          return value == "normal" ? 1 : value.replace(/[^\d.]*/gi, "")
        }
      }
    }
  };
  UE.plugins["insertcode"] = function () {
    var me = this;
    me.setOpt("insertcode", {
      as3: "ActionScript3",
      bash: "Bash/Shell",
      cpp: "C/C++",
      css: "Css",
      "c#": "C#",
      delphi: "Delphi",
      erlang: "Erlang",
      groovy: "Groovy",
      html: "Html",
      java: "Java",
      js: "Javascript",
      pl: "Perl",
      php: "PHP",
      plain: "Text",
      ps: "PowerShell",
      python: "Python",
      ruby: "Ruby",
      scala: "Scala",
      sql: "SQL",
      vb: "VB",
      xml: "XML",
      mind: "Mind"
    });
    me.commands["insertcode"] = {
      execCommand: function (cmd, lang) {
        var me = this, rng = me.selection.getRange(), pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
        if (pre) {
          pre.className = "brush:" + lang + ";toolbar:false;"
        } else {
          var code = "";
          if (rng.collapsed) {
            code = browser.ie && browser.ie11below ? browser.version <= 8 ? "&nbsp;" : "" : "<br/>"
          } else {
            var frag = rng.extractContents();
            var div = me.document.createElement("div");
            div.appendChild(frag);
            utils.each(UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")), me.options.filterTxtRules).children, function (node) {
              if (browser.ie && browser.ie11below && browser.version > 8) {
                if (node.type == "element") {
                  if (node.tagName == "br") {
                    code += "\n"
                  } else if (!dtd.$empty[node.tagName]) {
                    utils.each(node.children, function (cn) {
                      if (cn.type == "element") {
                        if (cn.tagName == "br") {
                          code += "\n"
                        } else if (!dtd.$empty[node.tagName]) {
                          code += cn.innerText()
                        }
                      } else {
                        code += cn.data
                      }
                    });
                    if (!/\n$/.test(code)) {
                      code += "\n"
                    }
                  }
                } else {
                  code += node.data + "\n"
                }
                if (!node.nextSibling() && /\n$/.test(code)) {
                  code = code.replace(/\n$/, "")
                }
              } else {
                if (browser.ie && browser.ie11below) {
                  if (node.type == "element") {
                    if (node.tagName == "br") {
                      code += "<br>"
                    } else if (!dtd.$empty[node.tagName]) {
                      utils.each(node.children, function (cn) {
                        if (cn.type == "element") {
                          if (cn.tagName == "br") {
                            code += "<br>"
                          } else if (!dtd.$empty[node.tagName]) {
                            code += cn.innerText()
                          }
                        } else {
                          code += cn.data
                        }
                      });
                      if (!/br>$/.test(code)) {
                        code += "<br>"
                      }
                    }
                  } else {
                    code += node.data + "<br>"
                  }
                  if (!node.nextSibling() && /<br>$/.test(code)) {
                    code = code.replace(/<br>$/, "")
                  }
                } else {
                  code += node.type == "element" ? dtd.$empty[node.tagName] ? "" : node.innerText() : node.data;
                  if (!/br\/?\s*>$/.test(code)) {
                    if (!node.nextSibling()) return;
                    code += "<br>"
                  }
                }
              }
            })
          }
          me.execCommand("inserthtml", '<pre id="coder"class="brush:' + lang + ';toolbar:false">' + code + "</pre>", true);
          pre = me.document.getElementById("coder");
          domUtils.removeAttributes(pre, "id");
          var tmpNode = pre.previousSibling;
          if (tmpNode && (tmpNode.nodeType == 3 && tmpNode.nodeValue.length == 1 && browser.ie && browser.version == 6 || domUtils.isEmptyBlock(tmpNode))) {
            domUtils.remove(tmpNode)
          }
          var rng = me.selection.getRange();
          if (domUtils.isEmptyBlock(pre)) {
            rng.setStart(pre, 0).setCursor(false, true)
          } else {
            rng.selectNodeContents(pre).select()
          }
        }
      }, queryCommandValue: function () {
        var path = this.selection.getStartElementPath();
        var lang = "";
        utils.each(path, function (node) {
          if (node.nodeName == "PRE") {
            var match = node.className.match(/brush:([^;]+)/);
            lang = match && match[1] ? match[1] : "";
            return false
          }
        });
        return lang
      }
    };
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName("pre"), function (pre) {
        var brs = pre.getNodesByTagName("br");
        if (brs.length) {
          browser.ie && browser.ie11below && browser.version > 8 && utils.each(brs, function (br) {
            var txt = UE.uNode.createText("\n");
            br.parentNode.insertBefore(txt, br);
            br.parentNode.removeChild(br)
          });
          return
        }
        if (browser.ie && browser.ie11below && browser.version > 8) return;
        var code = pre.innerText().split(/\n/);
        pre.innerHTML("");
        utils.each(code, function (c) {
          if (c.length) {
            pre.appendChild(UE.uNode.createText(c))
          }
          pre.appendChild(UE.uNode.createElement("br"))
        })
      })
    });
    me.addOutputRule(function (root) {
      utils.each(root.getNodesByTagName("pre"), function (pre) {
        var code = "";
        utils.each(pre.children, function (n) {
          if (n.type == "text") {
            code += n.data.replace(/[ ]/g, "&nbsp;").replace(/\n$/, "")
          } else {
            if (n.tagName == "br") {
              code += "\n"
            } else {
              code += !dtd.$empty[n.tagName] ? "" : n.innerText()
            }
          }
        });
        pre.innerText(code.replace(/(&nbsp;|\n)+$/, ""))
      })
    });
    me.notNeedCodeQuery = {help: 1, undo: 1, redo: 1, source: 1, print: 1, searchreplace: 1, fullscreen: 1, preview: 1, insertparagraph: 1, elementpath: 1, insertcode: 1, inserthtml: 1, selectall: 1};
    var orgQuery = me.queryCommandState;
    me.queryCommandState = function (cmd) {
      var me = this;
      if (!me.notNeedCodeQuery[cmd.toLowerCase()] && me.selection && me.queryCommandValue("insertcode")) {
        return -1
      }
      return UE.Editor.prototype.queryCommandState.apply(this, arguments)
    };
    me.addListener("beforeenterkeydown", function () {
      var rng = me.selection.getRange();
      var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
      if (pre) {
        me.fireEvent("saveScene");
        if (!rng.collapsed) {
          rng.deleteContents()
        }
        if (!browser.ie || browser.ie9above) {
          var tmpNode = me.document.createElement("br"), pre;
          rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);
          var next = tmpNode.nextSibling;
          if (!next && (!browser.ie || browser.version > 10)) {
            rng.insertNode(tmpNode.cloneNode(false))
          } else {
            rng.setStartAfter(tmpNode)
          }
          pre = tmpNode.previousSibling;
          var tmp;
          while (pre) {
            tmp = pre;
            pre = pre.previousSibling;
            if (!pre || pre.nodeName == "BR") {
              pre = tmp;
              break
            }
          }
          if (pre) {
            var str = "";
            while (pre && pre.nodeName != "BR" && new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue)) {
              str += pre.nodeValue;
              pre = pre.nextSibling
            }
            if (pre.nodeName != "BR") {
              var match = pre.nodeValue.match(new RegExp("^([\\s" + domUtils.fillChar + "]+)"));
              if (match && match[1]) {
                str += match[1]
              }
            }
            if (str) {
              str = me.document.createTextNode(str);
              rng.insertNode(str).setStartAfter(str)
            }
          }
          rng.collapse(true).select(true)
        } else {
          if (browser.version > 8) {
            var txt = me.document.createTextNode("\n");
            var start = rng.startContainer;
            if (rng.startOffset == 0) {
              var preNode = start.previousSibling;
              if (preNode) {
                rng.insertNode(txt);
                var fillchar = me.document.createTextNode(" ");
                rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true)
              }
            } else {
              rng.insertNode(txt).setStartAfter(txt);
              var fillchar = me.document.createTextNode(" ");
              start = rng.startContainer.childNodes[rng.startOffset];
              if (start && !/^\n/.test(start.nodeValue)) {
                rng.setStartBefore(txt)
              }
              rng.insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true)
            }
          } else {
            var tmpNode = me.document.createElement("br");
            rng.insertNode(tmpNode);
            rng.insertNode(me.document.createTextNode(domUtils.fillChar));
            rng.setStartAfter(tmpNode);
            pre = tmpNode.previousSibling;
            var tmp;
            while (pre) {
              tmp = pre;
              pre = pre.previousSibling;
              if (!pre || pre.nodeName == "BR") {
                pre = tmp;
                break
              }
            }
            if (pre) {
              var str = "";
              while (pre && pre.nodeName != "BR" && new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue)) {
                str += pre.nodeValue;
                pre = pre.nextSibling
              }
              if (pre.nodeName != "BR") {
                var match = pre.nodeValue.match(new RegExp("^([ " + domUtils.fillChar + "]+)"));
                if (match && match[1]) {
                  str += match[1]
                }
              }
              str = me.document.createTextNode(str);
              rng.insertNode(str).setStartAfter(str)
            }
            rng.collapse(true).select()
          }
        }
        me.fireEvent("saveScene");
        return true
      }
    });
    me.addListener("tabkeydown", function (cmd, evt) {
      var rng = me.selection.getRange();
      var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
      if (pre) {
        me.fireEvent("saveScene");
        if (evt.shiftKey) {
        } else {
          if (!rng.collapsed) {
            var bk = rng.createBookmark();
            var start = bk.start.previousSibling;
            while (start) {
              if (pre.firstChild === start && !domUtils.isBr(start)) {
                pre.insertBefore(me.document.createTextNode("    "), start);
                break
              }
              if (domUtils.isBr(start)) {
                pre.insertBefore(me.document.createTextNode("    "), start.nextSibling);
                break
              }
              start = start.previousSibling
            }
            var end = bk.end;
            start = bk.start.nextSibling;
            if (pre.firstChild === bk.start) {
              pre.insertBefore(me.document.createTextNode("    "), start.nextSibling)
            }
            while (start && start !== end) {
              if (domUtils.isBr(start) && start.nextSibling) {
                if (start.nextSibling === end) {
                  break
                }
                pre.insertBefore(me.document.createTextNode("    "), start.nextSibling)
              }
              start = start.nextSibling
            }
            rng.moveToBookmark(bk).select()
          } else {
            var tmpNode = me.document.createTextNode("    ");
            rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true)
          }
        }
        me.fireEvent("saveScene");
        return true
      }
    });
    me.addListener("beforeinserthtml", function (evtName, html) {
      var me = this, rng = me.selection.getRange(), pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
      if (pre) {
        if (!rng.collapsed) {
          rng.deleteContents()
        }
        var htmlstr = "";
        if (browser.ie && browser.version > 8) {
          utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function (node) {
            if (node.type == "element") {
              if (node.tagName == "br") {
                htmlstr += "\n"
              } else if (!dtd.$empty[node.tagName]) {
                utils.each(node.children, function (cn) {
                  if (cn.type == "element") {
                    if (cn.tagName == "br") {
                      htmlstr += "\n"
                    } else if (!dtd.$empty[node.tagName]) {
                      htmlstr += cn.innerText()
                    }
                  } else {
                    htmlstr += cn.data
                  }
                });
                if (!/\n$/.test(htmlstr)) {
                  htmlstr += "\n"
                }
              }
            } else {
              htmlstr += node.data + "\n"
            }
            if (!node.nextSibling() && /\n$/.test(htmlstr)) {
              htmlstr = htmlstr.replace(/\n$/, "")
            }
          });
          var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/&nbsp;/g, " ")));
          rng.insertNode(tmpNode).selectNode(tmpNode).select()
        } else {
          var frag = me.document.createDocumentFragment();
          utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function (node) {
            if (node.type == "element") {
              if (node.tagName == "br") {
                frag.appendChild(me.document.createElement("br"))
              } else if (!dtd.$empty[node.tagName]) {
                utils.each(node.children, function (cn) {
                  if (cn.type == "element") {
                    if (cn.tagName == "br") {
                      frag.appendChild(me.document.createElement("br"))
                    } else if (!dtd.$empty[node.tagName]) {
                      frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/&nbsp;/g, " "))))
                    }
                  } else {
                    frag.appendChild(me.document.createTextNode(utils.html(cn.data.replace(/&nbsp;/g, " "))))
                  }
                });
                if (frag.lastChild.nodeName != "BR") {
                  frag.appendChild(me.document.createElement("br"))
                }
              }
            } else {
              frag.appendChild(me.document.createTextNode(utils.html(node.data.replace(/&nbsp;/g, " "))))
            }
            if (!node.nextSibling() && frag.lastChild.nodeName == "BR") {
              frag.removeChild(frag.lastChild)
            }
          });
          rng.insertNode(frag).select()
        }
        return true
      }
    });
    me.addListener("keydown", function (cmd, evt) {
      var me = this, keyCode = evt.keyCode || evt.which;
      if (keyCode == 40) {
        var rng = me.selection.getRange(), pre, start = rng.startContainer;
        if (rng.collapsed && (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) && !pre.nextSibling) {
          var last = pre.lastChild;
          while (last && last.nodeName == "BR") {
            last = last.previousSibling
          }
          if (last === start || rng.startContainer === pre && rng.startOffset == pre.childNodes.length) {
            me.execCommand("insertparagraph");
            domUtils.preventDefault(evt)
          }
        }
      }
    });
    me.addListener("delkeydown", function (type, evt) {
      var rng = this.selection.getRange();
      rng.txtToElmBoundary(true);
      var start = rng.startContainer;
      if (domUtils.isTagNode(start, "pre") && rng.collapsed && domUtils.isStartInblock(rng)) {
        var p = me.document.createElement("p");
        domUtils.fillNode(me.document, p);
        start.parentNode.insertBefore(p, start);
        domUtils.remove(start);
        rng.setStart(p, 0).setCursor(false, true);
        domUtils.preventDefault(evt);
        return true
      }
    })
  };
  UE.commands["cleardoc"] = {
    execCommand: function (cmdName) {
      var me = this, enterTag = me.options.enterTag, range = me.selection.getRange();
      if (enterTag == "br") {
        me.body.innerHTML = "<br/>";
        range.setStart(me.body, 0).setCursor()
      } else {
        me.body.innerHTML = "<p>" + (ie ? "" : "<br/>") + "</p>";
        range.setStart(me.body.firstChild, 0).setCursor(false, true)
      }
      setTimeout(function () {
        me.fireEvent("clearDoc")
      }, 0)
    }
  };
  UE.plugin.register("anchor", function () {
    return {
      bindEvents: {
        ready: function () {
          utils.cssRule("anchor", ".anchorclass{background: url('" + this.options.themePath + this.options.theme + "/images/anchor.gif') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}", this.document)
        }
      }, outputRule: function (root) {
        utils.each(root.getNodesByTagName("img"), function (a) {
          var val;
          if (val = a.getAttr("anchorname")) {
            a.tagName = "a";
            a.setAttr({anchorname: "", name: val, class: ""})
          }
        })
      }, inputRule: function (root) {
        utils.each(root.getNodesByTagName("a"), function (a) {
          var val;
          if ((val = a.getAttr("name")) && !a.getAttr("href")) {
            if (/^\_Toc\d+$/.test(val)) {
              a.parentNode.removeChild(a);
              return
            }
            a.tagName = "img";
            a.setAttr({anchorname: a.getAttr("name"), class: "anchorclass"});
            a.setAttr("name")
          }
        })
      }, commands: {
        anchor: {
          execCommand: function (cmd, name) {
            var range = this.selection.getRange(), img = range.getClosedNode();
            if (img && img.getAttribute("anchorname")) {
              if (name) {
                img.setAttribute("anchorname", name)
              } else {
                range.setStartBefore(img).setCursor();
                domUtils.remove(img)
              }
            } else {
              if (name) {
                var anchor = this.document.createElement("img");
                range.collapse(true);
                domUtils.setAttributes(anchor, {anchorname: name, class: "anchorclass"});
                range.insertNode(anchor).setStartAfter(anchor).setCursor(false, true)
              }
            }
          }
        }
      }
    }
  });
  UE.plugins["wordcount"] = function () {
    var me = this;
    me.setOpt("wordCount", true);
    me.addListener("contentchange", function () {
      me.fireEvent("wordcount")
    });
    var timer;
    me.addListener("ready", function () {
      var me = this;
      domUtils.on(me.body, "keyup", function (evt) {
        var code = evt.keyCode || evt.which, ignores = {16: 1, 18: 1, 20: 1, 37: 1, 38: 1, 39: 1, 40: 1};
        if (code in ignores) return;
        clearTimeout(timer);
        timer = setTimeout(function () {
          me.fireEvent("wordcount")
        }, 200)
      })
    })
  };
  UE.plugins["pagebreak"] = function () {
    var me = this, notBreakTags = ["td"];
    me.setOpt("pageBreakTag", "_ueditor_page_break_tag_");

    function fillNode(node) {
      if (domUtils.isEmptyBlock(node)) {
        var firstChild = node.firstChild, tmpNode;
        while (firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)) {
          tmpNode = firstChild;
          firstChild = firstChild.firstChild
        }
        !tmpNode && (tmpNode = node);
        domUtils.fillNode(me.document, tmpNode)
      }
    }

    me.ready(function () {
      utils.cssRule("pagebreak", ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}", me.document)
    });

    function isHr(node) {
      return node && node.nodeType == 1 && node.tagName == "HR" && node.className == "pagebreak"
    }

    me.addInputRule(function (root) {
      root.traversal(function (node) {
        if (node.type == "text" && node.data == me.options.pageBreakTag) {
          var hr = UE.uNode.createElement('<hr class="pagebreak" noshade="noshade" size="5" style="-webkit-user-select: none;">');
          node.parentNode.insertBefore(hr, node);
          node.parentNode.removeChild(node)
        }
      })
    });
    me.addOutputRule(function (node) {
      utils.each(node.getNodesByTagName("hr"), function (n) {
        if (n.getAttr("class") == "pagebreak") {
          var txt = UE.uNode.createText(me.options.pageBreakTag);
          n.parentNode.insertBefore(txt, n);
          n.parentNode.removeChild(n)
        }
      })
    });
    me.commands["pagebreak"] = {
      execCommand: function () {
        var range = me.selection.getRange(), hr = me.document.createElement("hr");
        domUtils.setAttributes(hr, {class: "pagebreak", noshade: "noshade", size: "5"});
        domUtils.unSelectable(hr);
        var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true), parents = [], pN;
        if (node) {
          switch (node.tagName) {
            case"TD":
              pN = node.parentNode;
              if (!pN.previousSibling) {
                var table = domUtils.findParentByTagName(pN, "table");
                table.parentNode.insertBefore(hr, table);
                parents = domUtils.findParents(hr, true)
              } else {
                pN.parentNode.insertBefore(hr, pN);
                parents = domUtils.findParents(hr)
              }
              pN = parents[1];
              if (hr !== pN) {
                domUtils.breakParent(hr, pN)
              }
              me.fireEvent("afteradjusttable", me.document)
          }
        } else {
          if (!range.collapsed) {
            range.deleteContents();
            var start = range.startContainer;
            while (!domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) {
              range.setStartBefore(start).collapse(true);
              domUtils.remove(start);
              start = range.startContainer
            }
          }
          range.insertNode(hr);
          var pN = hr.parentNode, nextNode;
          while (!domUtils.isBody(pN)) {
            domUtils.breakParent(hr, pN);
            nextNode = hr.nextSibling;
            if (nextNode && domUtils.isEmptyBlock(nextNode)) {
              domUtils.remove(nextNode)
            }
            pN = hr.parentNode
          }
          nextNode = hr.nextSibling;
          var pre = hr.previousSibling;
          if (isHr(pre)) {
            domUtils.remove(pre)
          } else {
            pre && fillNode(pre)
          }
          if (!nextNode) {
            var p = me.document.createElement("p");
            hr.parentNode.appendChild(p);
            domUtils.fillNode(me.document, p);
            range.setStart(p, 0).collapse(true)
          } else {
            if (isHr(nextNode)) {
              domUtils.remove(nextNode)
            } else {
              fillNode(nextNode)
            }
            range.setEndAfter(hr).collapse(false)
          }
          range.select(true)
        }
      }
    }
  };
  UE.plugin.register("wordimage", function () {
    var me = this, images = [];
    this.addListener("click", function (type, evt) {
      var el = evt.target || evt.srcElement;
      if ("IMG" == el.tagName && el.getAttribute("data-word-image")) {
        me.ui._dialogs.wordimageDialog && me.ui._dialogs.wordimageDialog.open()
      }
    });
    return {
      commands: {
        wordimage: {
          execCommand: function () {
            var images = domUtils.getElementsByTagName(me.body, "img");
            var urlList = [];
            for (var i = 0, ci; ci = images[i++];) {
              var url = ci.getAttribute("data-word-image");
              url && urlList.push(url)
            }
            return urlList
          }, queryCommandState: function () {
            images = domUtils.getElementsByTagName(me.body, "img");
            for (var i = 0, ci; ci = images[i++];) {
              if (ci.getAttribute("data-word-image")) {
                return 1
              }
            }
            return -1
          }, notNeedUndo: true
        }
      }, inputRule: function (root) {
        utils.each(root.getNodesByTagName("img"), function (img) {
          var attrs = img.attrs, flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43, opt = me.options, src = opt.UEDITOR_HOME_URL + "themes/default/images/spacer.gif";
          if (attrs["src"] && /^(?:(file:\/+))/.test(attrs["src"])) {
            img.setAttr({
              width: attrs.width,
              height: attrs.height,
              alt: attrs.alt,
              "data-word-image": attrs.src,
              src: src,
              style: "background:url(" + (flag ? opt.themePath + opt.theme + "/images/word.gif" : opt.langPath + opt.lang + "/images/localimage.png") + ") no-repeat center center;border:1px solid #ddd"
            })
          }
        })
      }
    }
  });
  UE.plugin.register("autosave", function () {
    var me = this, saveKey = null;

    function save(editor) {
      var saveData;
      if (!editor.hasContents()) {
        saveKey && me.removePreferences(saveKey);
        return
      }
      editor._autoSaveTimer = null;
      saveData = me.body.innerHTML;
      if (editor.fireEvent("beforeautosave", {content: saveData}) === false) {
        return
      }
      me.setPreferences(saveKey, saveData);
      editor.fireEvent("afterautosave", {content: saveData})
    }

    return {
      defaultOptions: {autoSaveEnable: true, autoSaveRestore: false, autoSaveKey: null}, bindEvents: {
        ready: function () {
          saveKey = me.getOpt("autoSaveKey");
          if (!saveKey) {
            var _suffix = "_DraftsData", key = null;
            if (me.key) {
              key = me.key + _suffix
            } else {
              key = (me.container.parentNode.id || "ue-common") + _suffix
            }
            saveKey = (location.protocol + location.host + location.pathname).replace(/[.:\/]/g, "_") + key
          }
          if (me.getOpt("autoSaveRestore")) {
            var data = me.getPreferences(saveKey);
            if (data) {
              me.body.innerHTML = data;
              me.fireEvent("showmessage", {type: "info", content: me.getLang("autosave").autoRestoreTip})
            }
          }
        }, beforesubmit: function () {
          if (!me.getOpt("autoSaveEnable") || !saveKey) {
            return
          }
          me.execCommand("clear_auto_save_content")
        }, contentchange: function () {
          if (!me.isReady) {
            return
          }
          if (!me.getOpt("autoSaveEnable") || !saveKey) {
            return
          }
          if (me._autoSaveTimer) {
            window.clearTimeout(me._autoSaveTimer)
          }
          me._autoSaveTimer = window.setTimeout(function () {
            save(me)
          }, 1e3)
        }
      }, commands: {
        clear_auto_save_content: {
          execCommand: function (cmd, name) {
            if (saveKey && me.getPreferences(saveKey)) {
              me.removePreferences(saveKey)
            }
          }, notNeedUndo: true, ignoreContentChange: true
        }, set_auto_save_content: {
          execCommand: function (cmd, name) {
            save(me)
          }, notNeedUndo: true, ignoreContentChange: true
        }, get_auto_save_content: {
          execCommand: function (cmd, name) {
            return me.getPreferences(saveKey) || ""
          }, notNeedUndo: true, ignoreContentChange: true
        }, auto_save_restore: {
          execCommand: function (cmd, name) {
            if (saveKey) {
              me.body.innerHTML = me.getPreferences(saveKey) || "<p>" + domUtils.fillHtml + "</p>";
              me.focus(true)
            }
          }, queryCommandState: function () {
            return saveKey ? me.getPreferences(saveKey) === null ? -1 : 0 : -1
          }, notNeedUndo: true, ignoreContentChange: true
        }
      }
    }
  });
  UE.plugin.register("formula", function () {
    var me = this, images = [];
    return {
      commands: {
        formula: {
          execCommand: function (cmdName, value) {
            var range = me.selection.getRange(), img = range.getClosedNode();
            value = encodeURIComponent(value);
            var formulaConfig = me.getOpt("formulaConfig");
            var src = formulaConfig.imageUrlTemplate.replace(/\{\}/, value);
            if (img) {
              img.setAttribute("src", src)
            } else {
              me.execCommand("insertHtml", '<img src="' + src + '" data-formula-image="' + value + '" />')
            }
          }
        }
      }
    }
  });
  UE.plugins["dragdrop"] = function () {
    var me = this;
    me.ready(function () {
      domUtils.on(this.body, "dragend", function () {
        var rng = me.selection.getRange();
        var node = rng.getClosedNode() || me.selection.getStart();
        if (node && node.tagName == "IMG") {
          var pre = node.previousSibling, next;
          while (next = node.nextSibling) {
            if (next.nodeType == 1 && next.tagName == "SPAN" && !next.firstChild) {
              domUtils.remove(next)
            } else {
              break
            }
          }
          if ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre) || !pre) && (!next || next && !domUtils.isEmptyBlock(next))) {
            if (pre && pre.tagName == "P" && !domUtils.isEmptyBlock(pre)) {
              pre.appendChild(node);
              domUtils.moveChild(next, pre);
              domUtils.remove(next)
            } else if (next && next.tagName == "P" && !domUtils.isEmptyBlock(next)) {
              next.insertBefore(node, next.firstChild)
            }
            if (pre && pre.tagName == "P" && domUtils.isEmptyBlock(pre)) {
              domUtils.remove(pre)
            }
            if (next && next.tagName == "P" && domUtils.isEmptyBlock(next)) {
              domUtils.remove(next)
            }
            rng.selectNode(node).select();
            me.fireEvent("saveScene")
          }
        }
      })
    });
    me.addListener("keyup", function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 13) {
        var rng = me.selection.getRange(), node;
        if (node = domUtils.findParentByTagName(rng.startContainer, "p", true)) {
          if (domUtils.getComputedStyle(node, "text-align") == "center") {
            domUtils.removeStyle(node, "text-align")
          }
        }
      }
    })
  };
  UE.plugins["undo"] = function () {
    var saveSceneTimer;
    var me = this, maxUndoCount = me.options.maxUndoCount || 20, maxInputCount = me.options.maxInputCount || 20, fillchar = new RegExp(domUtils.fillChar + "|</hr>", "gi");
    var noNeedFillCharTags = {ol: 1, ul: 1, table: 1, tbody: 1, tr: 1, body: 1};
    var orgState = me.options.autoClearEmptyNode;

    function compareAddr(indexA, indexB) {
      if (indexA.length != indexB.length) return 0;
      for (var i = 0, l = indexA.length; i < l; i++) {
        if (indexA[i] != indexB[i]) return 0
      }
      return 1
    }

    function compareRangeAddress(rngAddrA, rngAddrB) {
      if (rngAddrA.collapsed != rngAddrB.collapsed) {
        return 0
      }
      if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {
        return 0
      }
      return 1
    }

    function UndoManager() {
      this.list = [];
      this.index = 0;
      this.hasUndo = false;
      this.hasRedo = false;
      this.undo = function () {
        if (this.hasUndo) {
          if (!this.list[this.index - 1] && this.list.length == 1) {
            this.reset();
            return
          }
          while (this.list[this.index].content == this.list[this.index - 1].content) {
            this.index--;
            if (this.index == 0) {
              return this.restore(0)
            }
          }
          this.restore(--this.index)
        }
      };
      this.redo = function () {
        if (this.hasRedo) {
          while (this.list[this.index].content == this.list[this.index + 1].content) {
            this.index++;
            if (this.index == this.list.length - 1) {
              return this.restore(this.index)
            }
          }
          this.restore(++this.index)
        }
      };
      this.restore = function () {
        var me = this.editor;
        var scene = this.list[this.index];
        var root = UE.htmlparser(scene.content.replace(fillchar, ""));
        me.options.autoClearEmptyNode = false;
        me.filterInputRule(root);
        me.options.autoClearEmptyNode = orgState;
        me.document.body.innerHTML = root.toHtml();
        me.fireEvent("afterscencerestore");
        if (browser.ie) {
          utils.each(domUtils.getElementsByTagName(me.document, "td th caption p"), function (node) {
            if (domUtils.isEmptyNode(node)) {
              domUtils.fillNode(me.document, node)
            }
          })
        }
        try {
          var rng = new dom.Range(me.document).moveToAddress(scene.address);
          rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()])
        } catch (e) {
        }
        this.update();
        this.clearKey();
        me.fireEvent("reset", true)
      };
      this.getScene = function () {
        var me = this.editor;
        var rng = me.selection.getRange(), rngAddress = rng.createAddress(false, true);
        me.fireEvent("beforegetscene");
        var root = UE.htmlparser(me.body.innerHTML);
        me.options.autoClearEmptyNode = false;
        me.filterOutputRule(root);
        me.options.autoClearEmptyNode = orgState;
        var cont = root.toHtml();
        me.fireEvent("aftergetscene");
        return {address: rngAddress, content: cont}
      };
      this.save = function (notCompareRange, notSetCursor) {
        clearTimeout(saveSceneTimer);
        var currentScene = this.getScene(notSetCursor), lastScene = this.list[this.index];
        if (!lastScene || lastScene && lastScene.content != currentScene.content) {
          setTimeout(function () {
            me.trigger("contentchange")
          }, 0)
        }
        if (lastScene && lastScene.content == currentScene.content && (notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address))) {
          return
        }
        this.list = this.list.slice(0, this.index + 1);
        this.list.push(currentScene);
        if (this.list.length > maxUndoCount) {
          this.list.shift()
        }
        this.index = this.list.length - 1;
        this.clearKey();
        this.update()
      };
      this.update = function () {
        this.hasRedo = !!this.list[this.index + 1];
        this.hasUndo = !!this.list[this.index - 1]
      };
      this.reset = function () {
        this.list = [];
        this.index = 0;
        this.hasUndo = false;
        this.hasRedo = false;
        this.clearKey()
      };
      this.clearKey = function () {
        keycont = 0;
        lastKeyCode = null
      }
    }

    me.undoManger = new UndoManager;
    me.undoManger.editor = me;

    function saveScene() {
      this.undoManger.save()
    }

    me.addListener("saveScene", function () {
      var args = Array.prototype.splice.call(arguments, 1);
      this.undoManger.save.apply(this.undoManger, args)
    });
    me.addListener("reset", function (type, exclude) {
      if (!exclude) {
        this.undoManger.reset()
      }
    });
    me.commands["redo"] = me.commands["undo"] = {
      execCommand: function (cmdName) {
        this.undoManger[cmdName]()
      }, queryCommandState: function (cmdName) {
        return this.undoManger["has" + (cmdName.toLowerCase() == "undo" ? "Undo" : "Redo")] ? 0 : -1
      }, notNeedUndo: 1
    };
    var keys = {16: 1, 17: 1, 18: 1, 37: 1, 38: 1, 39: 1, 40: 1}, keycont = 0, lastKeyCode;
    var inputType = false;
    me.addListener("ready", function () {
      domUtils.on(this.body, "compositionstart", function () {
        inputType = true
      });
      domUtils.on(this.body, "compositionend", function () {
        inputType = false
      })
    });
    me.addshortcutkey({Undo: "ctrl+90", Redo: "ctrl+89"});
    var isCollapsed = true;
    me.addListener("keyup", function (type, evt) {
      var me = this;
      var keyCode = evt.keyCode || evt.which;
      if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
        if (inputType) return;
        if (!me.selection.getRange().collapsed) {
          me.undoManger.save(false, true);
          isCollapsed = false;
          return
        }
        if (me.undoManger.list.length === 0) {
          me.undoManger.save(true)
        }
        clearTimeout(saveSceneTimer);

        function save(cont) {
          cont.undoManger.save(false, true);
          cont.fireEvent("selectionchange")
        }

        saveSceneTimer = setTimeout(function () {
          if (inputType) {
            var intervalTimer = setInterval(function () {
              if (!inputType) {
                save(me);
                clearInterval(intervalTimer)
              }
            }, 300);
            return
          }
          save(me)
        }, 200);
        lastKeyCode = keyCode;
        keycont++;
        if (keycont >= maxInputCount) {
          save(me)
        }
      }
    });
    me.addListener("keyup", function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
        if (inputType) return;
        if (!isCollapsed) {
          this.undoManger.save(false, true);
          isCollapsed = true
        }
      }
    });
    me.stopCmdUndo = function () {
      me.__hasEnterExecCommand = true
    };
    me.startCmdUndo = function () {
      me.__hasEnterExecCommand = false
    }
  };
  UE.plugin.register("copy", function () {
    var me = this;

    function initZeroClipboard() {
      ZeroClipboard.config({debug: false, swfPath: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.swf"});
      var client = me.zeroclipboard = new ZeroClipboard;
      client.on("copy", function (e) {
        var client = e.client, rng = me.selection.getRange(), div = document.createElement("div");
        div.appendChild(rng.cloneContents());
        client.setText(div.innerText || div.textContent);
        client.setHtml(div.innerHTML);
        rng.select()
      });
      client.on("mouseover mouseout", function (e) {
        var target = e.target;
        if (target) {
          if (e.type == "mouseover") {
            domUtils.addClass(target, "edui-state-hover")
          } else if (e.type == "mouseout") {
            domUtils.removeClasses(target, "edui-state-hover")
          }
        }
      });
      client.on("wrongflash noflash", function () {
        ZeroClipboard.destroy()
      });
      me.fireEvent("zeroclipboardready", client)
    }

    return {
      bindEvents: {
        ready: function () {
          if (!browser.ie) {
            if (window.ZeroClipboard) {
              initZeroClipboard()
            } else {
              utils.loadFile(document, {src: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.js", tag: "script", type: "text/javascript", defer: "defer"}, function () {
                initZeroClipboard()
              })
            }
          }
        }
      }, commands: {
        copy: {
          execCommand: function (cmd) {
            if (!me.document.execCommand("copy")) {
              alert(me.getLang("copymsg"))
            }
          }
        }
      }
    }
  });
  UE.plugins["paste"] = function () {
    function getClipboardData(callback) {
      var doc = this.document;
      if (doc.getElementById("baidu_pastebin")) {
        return
      }
      var range = this.selection.getRange(), bk = range.createBookmark(), pastebin = doc.createElement("div");
      pastebin.id = "baidu_pastebin";
      browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar));
      doc.body.appendChild(pastebin);
      bk.start.style.display = "";
      pastebin.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + domUtils.getXY(bk.start).y + "px";
      range.selectNodeContents(pastebin).select(true);
      setTimeout(function () {
        if (browser.webkit) {
          for (var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi; pi = pastebins[i++];) {
            if (domUtils.isEmptyNode(pi)) {
              domUtils.remove(pi)
            } else {
              pastebin = pi;
              break
            }
          }
        }
        try {
          pastebin.parentNode.removeChild(pastebin)
        } catch (e) {
        }
        range.moveToBookmark(bk).select(true);
        callback(pastebin)
      }, 0)
    }

    var me = this;
    me.setOpt({retainOnlyLabelPasted: false});
    var txtContent, htmlContent, address;

    function getPureHtml(html) {
      return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function (a, b, tagName, attrs) {
        tagName = tagName.toLowerCase();
        if ({img: 1}[tagName]) {
          return a
        }
        attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, function (str, atr, val) {
          if ({src: 1, href: 1, name: 1}[atr.toLowerCase()]) {
            return atr + "=" + val + " "
          }
          return ""
        });
        if ({span: 1, div: 1}[tagName]) {
          return ""
        } else {
          return "<" + b + tagName + " " + utils.trim(attrs) + ">"
        }
      })
    }

    function filter(div) {
      var html;
      if (div.firstChild) {
        var nodes = domUtils.getElementsByTagName(div, "span");
        for (var i = 0, ni; ni = nodes[i++];) {
          if (ni.id == "_baidu_cut_start" || ni.id == "_baidu_cut_end") {
            domUtils.remove(ni)
          }
        }
        if (browser.webkit) {
          var brs = div.querySelectorAll("div br");
          for (var i = 0, bi; bi = brs[i++];) {
            var pN = bi.parentNode;
            if (pN.tagName == "DIV" && pN.childNodes.length == 1) {
              pN.innerHTML = "<p><br/></p>";
              domUtils.remove(pN)
            }
          }
          var divs = div.querySelectorAll("#baidu_pastebin");
          for (var i = 0, di; di = divs[i++];) {
            var tmpP = me.document.createElement("p");
            di.parentNode.insertBefore(tmpP, di);
            while (di.firstChild) {
              tmpP.appendChild(di.firstChild)
            }
            domUtils.remove(di)
          }
          var metas = div.querySelectorAll("meta");
          for (var i = 0, ci; ci = metas[i++];) {
            domUtils.remove(ci)
          }
          var brs = div.querySelectorAll("br");
          for (i = 0; ci = brs[i++];) {
            if (/^apple-/i.test(ci.className)) {
              domUtils.remove(ci)
            }
          }
        }
        if (browser.gecko) {
          var dirtyNodes = div.querySelectorAll("[_moz_dirty]");
          for (i = 0; ci = dirtyNodes[i++];) {
            ci.removeAttribute("_moz_dirty")
          }
        }
        if (!browser.ie) {
          var spans = div.querySelectorAll("span.Apple-style-span");
          for (var i = 0, ci; ci = spans[i++];) {
            domUtils.remove(ci, true)
          }
        }
        html = div.innerHTML;
        html = UE.filterWord(html);
        var root = UE.htmlparser(html);
        if (me.options.filterRules) {
          UE.filterNode(root, me.options.filterRules)
        }
        me.filterInputRule(root);
        if (browser.webkit) {
          var br = root.lastChild();
          if (br && br.type == "element" && br.tagName == "br") {
            root.removeChild(br)
          }
          utils.each(me.body.querySelectorAll("div"), function (node) {
            if (domUtils.isEmptyBlock(node)) {
              domUtils.remove(node, true)
            }
          })
        }
        html = {html: root.toHtml()};
        me.fireEvent("beforepaste", html, root);
        if (!html.html) {
          return
        }
        root = UE.htmlparser(html.html, true);
        if (me.queryCommandState("pasteplain") === 1) {
          me.execCommand("insertHtml", UE.filterNode(root, me.options.filterTxtRules).toHtml(), true)
        } else {
          UE.filterNode(root, me.options.filterTxtRules);
          txtContent = root.toHtml();
          htmlContent = html.html;
          address = me.selection.getRange().createAddress(true);
          me.execCommand("insertHtml", me.getOpt("retainOnlyLabelPasted") === true ? getPureHtml(htmlContent) : htmlContent, true)
        }
        me.fireEvent("afterpaste", html)
      }
    }

    me.addListener("pasteTransfer", function (cmd, plainType) {
      if (address && txtContent && htmlContent && txtContent != htmlContent) {
        var range = me.selection.getRange();
        range.moveToAddress(address, true);
        if (!range.collapsed) {
          while (!domUtils.isBody(range.startContainer)) {
            var start = range.startContainer;
            if (start.nodeType == 1) {
              start = start.childNodes[range.startOffset];
              if (!start) {
                range.setStartBefore(range.startContainer);
                continue
              }
              var pre = start.previousSibling;
              if (pre && pre.nodeType == 3 && new RegExp("^[\n\r\t " + domUtils.fillChar + "]*$").test(pre.nodeValue)) {
                range.setStartBefore(pre)
              }
            }
            if (range.startOffset == 0) {
              range.setStartBefore(range.startContainer)
            } else {
              break
            }
          }
          while (!domUtils.isBody(range.endContainer)) {
            var end = range.endContainer;
            if (end.nodeType == 1) {
              end = end.childNodes[range.endOffset];
              if (!end) {
                range.setEndAfter(range.endContainer);
                continue
              }
              var next = end.nextSibling;
              if (next && next.nodeType == 3 && new RegExp("^[\n\r\t" + domUtils.fillChar + "]*$").test(next.nodeValue)) {
                range.setEndAfter(next)
              }
            }
            if (range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
              range.setEndAfter(range.endContainer)
            } else {
              break
            }
          }
        }
        range.deleteContents();
        range.select(true);
        me.__hasEnterExecCommand = true;
        var html = htmlContent;
        if (plainType === 2) {
          html = getPureHtml(html)
        } else if (plainType) {
          html = txtContent
        }
        me.execCommand("inserthtml", html, true);
        me.__hasEnterExecCommand = false;
        var rng = me.selection.getRange();
        while (!domUtils.isBody(rng.startContainer) && !rng.startOffset && rng.startContainer[rng.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
          rng.setStartBefore(rng.startContainer)
        }
        var tmpAddress = rng.createAddress(true);
        address.endAddress = tmpAddress.startAddress
      }
    });
    me.addListener("ready", function () {
      domUtils.on(me.body, "cut", function () {
        var range = me.selection.getRange();
        if (!range.collapsed && me.undoManger) {
          me.undoManger.save()
        }
      });
      domUtils.on(me.body, browser.ie || browser.opera ? "keydown" : "paste", function (e) {
        if ((browser.ie || browser.opera) && (!e.ctrlKey && !e.metaKey || e.keyCode != "86")) {
          return
        }
        getClipboardData.call(me, function (div) {
          filter(div)
        })
      })
    });
    me.commands["paste"] = {
      execCommand: function (cmd) {
        if (browser.ie) {
          getClipboardData.call(me, function (div) {
            filter(div)
          });
          me.document.execCommand("paste")
        } else {
          alert(me.getLang("pastemsg"))
        }
      }
    }
  };
  UE.plugins["pasteplain"] = function () {
    var me = this;
    me.setOpt({
      pasteplain: false, filterTxtRules: function () {
        function transP(node) {
          node.tagName = "p";
          node.setStyle()
        }

        function removeNode(node) {
          node.parentNode.removeChild(node, true)
        }

        return {
          "-": "script style object iframe embed input select", p: {$: {}}, br: {$: {}}, div: function (node) {
            var tmpNode, p = UE.uNode.createElement("p");
            while (tmpNode = node.firstChild()) {
              if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) {
                p.appendChild(tmpNode)
              } else {
                if (p.firstChild()) {
                  node.parentNode.insertBefore(p, node);
                  p = UE.uNode.createElement("p")
                } else {
                  node.parentNode.insertBefore(tmpNode, node)
                }
              }
            }
            if (p.firstChild()) {
              node.parentNode.insertBefore(p, node)
            }
            node.parentNode.removeChild(node)
          }, ol: removeNode, ul: removeNode, dl: removeNode, dt: removeNode, dd: removeNode, li: removeNode, caption: transP, th: transP, tr: transP, h1: transP, h2: transP, h3: transP, h4: transP, h5: transP, h6: transP, td: function (node) {
            var txt = !!node.innerText();
            if (txt) {
              node.parentNode.insertAfter(UE.uNode.createText(" &nbsp; &nbsp;"), node)
            }
            node.parentNode.removeChild(node, node.innerText())
          }
        }
      }()
    });
    var pasteplain = me.options.pasteplain;
    me.commands["pasteplain"] = {
      queryCommandState: function () {
        return pasteplain ? 1 : 0
      }, execCommand: function () {
        pasteplain = !pasteplain | 0
      }, notNeedUndo: 1
    }
  };
  UE.plugins["list"] = function () {
    var me = this, notExchange = {TD: 1, PRE: 1, BLOCKQUOTE: 1};
    me.setOpt({
      autoTransWordToList: false,
      insertorderedlist: {decimal: "", "lower-alpha": "", "lower-roman": "", "upper-alpha": "", "upper-roman": ""},
      insertunorderedlist: {circle: "", disc: "", square: ""},
      listDefaultPaddingLeft: "30",
      listiconpath: "http://bs.baidu.com/listicon/",
      maxListLevel: -1,
      disablePInList: false
    });

    function listToArray(list) {
      var arr = [];
      for (var p in list) {
        arr.push(p)
      }
      return arr
    }

    var listStyle = {OL: listToArray(me.options.insertorderedlist), UL: listToArray(me.options.insertunorderedlist)};
    var liiconpath = me.options.listiconpath;
    me.ready(function () {
      var customCss = [];
      customCss.push(".list-paddingleft-1{padding-left:0}");
      customCss.push(".list-paddingleft-2{padding-left:" + me.options.listDefaultPaddingLeft + "px}");
      customCss.push(".list-paddingleft-3{padding-left:" + me.options.listDefaultPaddingLeft * 2 + "px}");
      utils.cssRule("list", "ol,ul{margin:0;pading:0;" + (browser.ie ? "" : "width:95%") + "}li{clear:both;}" + customCss.join("\n"), me.document)
    });
    me.ready(function () {
      domUtils.on(me.body, "cut", function () {
        setTimeout(function () {
          var rng = me.selection.getRange(), li;
          if (!rng.collapsed) {
            if (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) {
              if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
                var pn = li.parentNode, node;
                if (node = pn.previousSibling) {
                  domUtils.remove(pn);
                  rng.setStartAtLast(node).collapse(true);
                  rng.select(true)
                } else if (node = pn.nextSibling) {
                  domUtils.remove(pn);
                  rng.setStartAtFirst(node).collapse(true);
                  rng.select(true)
                } else {
                  var tmpNode = me.document.createElement("p");
                  domUtils.fillNode(me.document, tmpNode);
                  pn.parentNode.insertBefore(tmpNode, pn);
                  domUtils.remove(pn);
                  rng.setStart(tmpNode, 0).collapse(true);
                  rng.select(true)
                }
              }
            }
          }
        })
      })
    });

    function getStyle(node) {
      var cls = node.className;
      if (domUtils.hasClass(node, /custom_/)) {
        return cls.match(/custom_(\w+)/)[1]
      }
      return domUtils.getStyle(node, "list-style-type")
    }

    me.addListener("beforepaste", function (type, html) {
      var me = this, rng = me.selection.getRange(), li;
      var root = UE.htmlparser(html.html, true);
      if (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) {
        var list = li.parentNode, tagName = list.tagName === "OL" ? "ul" : "ol";
        utils.each(root.getNodesByTagName(tagName), function (n) {
          n.tagName = list.tagName;
          n.setAttr();
          if (n.parentNode === root) {
            type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc")
          } else {
            var className = n.parentNode.getAttr("class");
            if (className && /custom_/.test(className)) {
              type = className.match(/custom_(\w+)/)[1]
            } else {
              type = n.parentNode.getStyle("list-style-type")
            }
            if (!type) {
              type = list.tagName === "OL" ? "decimal" : "disc"
            }
          }
          var index = utils.indexOf(listStyle[list.tagName], type);
          if (n.parentNode !== root) index = index + 1 === listStyle[list.tagName].length ? 0 : index + 1;
          var currentStyle = listStyle[list.tagName][index];
          n.setStyle("list-style-type", currentStyle)
        })
      }
      html.html = root.toHtml()
    });
    me.getOpt("disablePInList") === true && me.addOutputRule(function (root) {
      utils.each(root.getNodesByTagName("li"), function (li) {
        var newChildrens = [], index = 0;
        utils.each(li.children, function (n) {
          if (n.tagName == "p") {
            var tmpNode;
            while (tmpNode = n.children.pop()) {
              newChildrens.splice(index, 0, tmpNode);
              tmpNode.parentNode = li;
              lastNode = tmpNode
            }
            tmpNode = newChildrens[newChildrens.length - 1];
            if (!tmpNode || tmpNode.type !== "element" || tmpNode.tagName !== "br") {
              var br = UE.uNode.createElement("br");
              br.parentNode = li;
              newChildrens.push(br)
            }
            index = newChildrens.length
          }
        });
        if (newChildrens.length) {
          li.children = newChildrens
        }
      })
    });
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName("li"), function (li) {
        var tmpP = UE.uNode.createElement("p");
        for (var i = 0, ci; ci = li.children[i];) {
          if (ci.type === "text" || dtd.p[ci.tagName]) {
            tmpP.appendChild(ci)
          } else {
            if (tmpP.firstChild()) {
              li.insertBefore(tmpP, ci);
              tmpP = UE.uNode.createElement("p");
              i = i + 2
            } else {
              i++
            }
          }
        }
        if (tmpP.firstChild() && !tmpP.parentNode || !li.firstChild()) {
          li.appendChild(tmpP)
        }
        if (!tmpP.firstChild()) {
          tmpP.innerHTML(browser.ie ? "&nbsp;" : "<br/>")
        }
        var p = li.firstChild();
        var lastChild = p.lastChild();
        if (lastChild && lastChild.type === "text" && /^\s*$/.test(lastChild.data)) {
          p.removeChild(lastChild)
        }
      });
      if (me.options.autoTransWordToList) {
        var orderlisttype = {
          num1: /^\d+\)/,
          decimal: /^\d+\./,
          "lower-alpha": /^[a-z]+\)/,
          "upper-alpha": /^[A-Z]+\./,
          cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/,
          cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/
        }, unorderlisttype = {square: "n"};

        function checkListType(content, container) {
          var span = container.firstChild();
          if (span && span.type === "element" && span.tagName === "span" && /Wingdings|Symbol/.test(span.getStyle("font-family"))) {
            for (var p in unorderlisttype) {
              if (unorderlisttype[p] == span.data) {
                return p
              }
            }
            return "disc"
          }
          for (var p in orderlisttype) {
            if (orderlisttype[p].test(content)) {
              return p
            }
          }
        }

        utils.each(root.getNodesByTagName("p"), function (node) {
          if (node.getAttr("class") !== "MsoListParagraph") {
            return
          }
          node.setStyle("margin", "");
          node.setStyle("margin-left", "");
          node.setAttr("class", "");

          function appendLi(list, p, type) {
            if (list.tagName === "ol") {
              if (browser.ie) {
                var first = p.firstChild();
                if (first.type === "element" && first.tagName === "span" && orderlisttype[type].test(first.innerText())) {
                  p.removeChild(first)
                }
              } else {
                p.innerHTML(p.innerHTML().replace(orderlisttype[type], ""))
              }
            } else {
              p.removeChild(p.firstChild())
            }
            var li = UE.uNode.createElement("li");
            li.appendChild(p);
            list.appendChild(li)
          }

          var tmp = node, type, cacheNode = node;
          if (node.parentNode.tagName !== "li" && (type = checkListType(node.innerText(), node))) {
            var list = UE.uNode.createElement(me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul");
            list.setStyle("list-style-type", type);
            while (node && node.parentNode.tagName !== "li" && checkListType(node.innerText(), node)) {
              tmp = node.nextSibling();
              if (!tmp) {
                node.parentNode.insertBefore(list, node)
              }
              appendLi(list, node, type);
              node = tmp
            }
            if (!list.parentNode && node && node.parentNode) {
              node.parentNode.insertBefore(list, node)
            }
          }
          var span = cacheNode.firstChild();
          if (span && span.type == "element" && span.tagName == "span" && /^\s*(&nbsp;)+\s*$/.test(span.innerText())) {
            span.parentNode.removeChild(span)
          }
        })
      }
    });
    me.addListener("contentchange", function () {
      adjustListStyle(me.document)
    });

    function adjustListStyle(doc, ignore) {
      utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function (node) {
        if (!domUtils.inDoc(node, doc)) return;
        var parent = node.parentNode;
        if (parent.tagName === node.tagName) {
          var nodeStyleType = getStyle(node) || (node.tagName === "OL" ? "decimal" : "disc"), parentStyleType = getStyle(parent) || (parent.tagName === "OL" ? "decimal" : "disc");
          if (nodeStyleType === parentStyleType) {
            var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType);
            styleIndex = styleIndex + 1 === listStyle[node.tagName].length ? 0 : styleIndex + 1;
            setListStyle(node, listStyle[node.tagName][styleIndex])
          }
        }
        var index = 0, type = 2;
        if (domUtils.hasClass(node, /custom_/)) {
          if (!(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/))) {
            type = 1
          }
        } else {
          if (/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/)) {
            type = 3
          }
        }
        var style = domUtils.getStyle(node, "list-style-type");
        style && (node.style.cssText = "list-style-type:" + style);
        node.className = utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) + " list-paddingleft-" + type;
        utils.each(domUtils.getElementsByTagName(node, "li"), function (li) {
          li.style.cssText && (li.style.cssText = "");
          if (!li.firstChild) {
            domUtils.remove(li);
            return
          }
          if (li.parentNode !== node) {
            return
          }
          index++;
          if (domUtils.hasClass(node, /custom_/)) {
            var paddingLeft = 1, currentStyle = getStyle(node);
            if (node.tagName === "OL") {
              if (currentStyle) {
                switch (currentStyle) {
                  case"cn":
                  case"cn1":
                  case"cn2":
                    if (index > 10 && (index % 10 === 0 || index > 10 && index < 20)) {
                      paddingLeft = 2
                    } else if (index > 20) {
                      paddingLeft = 3
                    }
                    break;
                  case"num2":
                    if (index > 9) {
                      paddingLeft = 2
                    }
                }
              }
              li.className = "list-" + currentStyle + "-paddingleft-" + paddingLeft
            } else {
              li.className = "list-" + currentStyle + "-paddingleft"
            }
          } else {
            li.className = li.className.replace(/list-[\w\-]+/gi, "")
          }
          var className = li.getAttribute("class");
          if (className !== null && !className.replace(/\s/g, "")) {
            domUtils.removeAttributes(li, "class")
          }
        });
        !ignore && adjustList(node, node.tagName.toLowerCase(), getStyle(node) || domUtils.getStyle(node, "list-style-type"), true)
      })
    }

    function adjustList(list, tag, style, ignoreEmpty) {
      var nextList = list.nextSibling;
      if (nextList && nextList.nodeType === 1 && nextList.tagName.toLowerCase() === tag && (getStyle(nextList) || domUtils.getStyle(nextList, "list-style-type") || (tag == "ol" ? "decimal" : "disc")) == style) {
        domUtils.moveChild(nextList, list);
        if (nextList.childNodes.length === 0) {
          domUtils.remove(nextList)
        }
      }
      if (nextList && domUtils.isFillChar(nextList)) {
        domUtils.remove(nextList)
      }
      var preList = list.previousSibling;
      if (preList && preList.nodeType === 1 && preList.tagName.toLowerCase() == tag && (getStyle(preList) || domUtils.getStyle(preList, "list-style-type") || (tag == "ol" ? "decimal" : "disc")) === style) {
        domUtils.moveChild(list, preList)
      }
      if (preList && domUtils.isFillChar(preList)) {
        domUtils.remove(preList)
      }
      !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
      if (getStyle(list)) {
        adjustListStyle(list.ownerDocument, true)
      }
    }

    function setListStyle(list, style) {
      try {
        domUtils.setStyle(list, "list-style-type", style)
      } catch (e) {
      }
    }

    function clearEmptySibling(node) {
      var tmpNode = node.previousSibling;
      if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
        domUtils.remove(tmpNode)
      }
      tmpNode = node.nextSibling;
      if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
        domUtils.remove(tmpNode)
      }
    }

    me.addListener("keydown", function (type, evt) {
      function preventAndSave() {
        evt.preventDefault ? evt.preventDefault() : evt.returnValue = false;
        me.fireEvent("contentchange");
        me.undoManger && me.undoManger.save()
      }

      function findList(node, filterFn) {
        while (node && !domUtils.isBody(node)) {
          if (filterFn(node)) {
            return null
          }
          if (node.nodeType === 1 && /[ou]l/i.test(node.tagName)) {
            return node
          }
          node = node.parentNode
        }
        return null
      }

      var keyCode = evt.keyCode || evt.which;
      if (keyCode === 13 && !evt.shiftKey) {
        var rng = me.selection.getRange(), parent = domUtils.findParent(rng.startContainer, function (node) {
          return domUtils.isBlockElm(node)
        }, true), li = domUtils.findParentByTagName(rng.startContainer, "li", true);
        if (parent && parent.tagName !== "PRE" && !li) {
          var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, "g"), "");
          if (/^\s*1\s*\.[^\d]/.test(html)) {
            parent.innerHTML = html.replace(/^\s*1\s*\./, "");
            rng.setStartAtLast(parent).collapse(true).select();
            me.__hasEnterExecCommand = true;
            me.execCommand("insertorderedlist");
            me.__hasEnterExecCommand = false
          }
        }
        var range = me.selection.getRange(), start = findList(range.startContainer, function (node) {
          return node.tagName === "TABLE"
        }), end = range.collapsed ? start : findList(range.endContainer, function (node) {
          return node.tagName === "TABLE"
        });
        if (start && end && start === end) {
          if (!range.collapsed) {
            start = domUtils.findParentByTagName(range.startContainer, "li", true);
            end = domUtils.findParentByTagName(range.endContainer, "li", true);
            if (start && end && start === end) {
              range.deleteContents();
              li = domUtils.findParentByTagName(range.startContainer, "li", true);
              if (li && domUtils.isEmptyBlock(li)) {
                pre = li.previousSibling;
                next = li.nextSibling;
                p = me.document.createElement("p");
                domUtils.fillNode(me.document, p);
                parentList = li.parentNode;
                if (pre && next) {
                  range.setStart(next, 0).collapse(true).select(true);
                  domUtils.remove(li)
                } else {
                  if (!pre && !next || !pre) {
                    parentList.parentNode.insertBefore(p, parentList)
                  } else {
                    li.parentNode.parentNode.insertBefore(p, parentList.nextSibling)
                  }
                  domUtils.remove(li);
                  if (!parentList.firstChild) {
                    domUtils.remove(parentList)
                  }
                  range.setStart(p, 0).setCursor()
                }
                preventAndSave();
                return
              }
            } else {
              var tmpRange = range.cloneRange(), bk = tmpRange.collapse(false).createBookmark();
              range.deleteContents();
              tmpRange.moveToBookmark(bk);
              var li = domUtils.findParentByTagName(tmpRange.startContainer, "li", true);
              clearEmptySibling(li);
              tmpRange.select();
              preventAndSave();
              return
            }
          }
          li = domUtils.findParentByTagName(range.startContainer, "li", true);
          if (li) {
            if (domUtils.isEmptyBlock(li)) {
              bk = range.createBookmark();
              var parentList = li.parentNode;
              if (li !== parentList.lastChild) {
                domUtils.breakParent(li, parentList);
                clearEmptySibling(li)
              } else {
                parentList.parentNode.insertBefore(li, parentList.nextSibling);
                if (domUtils.isEmptyNode(parentList)) {
                  domUtils.remove(parentList)
                }
              }
              if (!dtd.$list[li.parentNode.tagName]) {
                if (!domUtils.isBlockElm(li.firstChild)) {
                  p = me.document.createElement("p");
                  li.parentNode.insertBefore(p, li);
                  while (li.firstChild) {
                    p.appendChild(li.firstChild)
                  }
                  domUtils.remove(li)
                } else {
                  domUtils.remove(li, true)
                }
              }
              range.moveToBookmark(bk).select()
            } else {
              var first = li.firstChild;
              if (!first || !domUtils.isBlockElm(first)) {
                var p = me.document.createElement("p");
                !li.firstChild && domUtils.fillNode(me.document, p);
                while (li.firstChild) {
                  p.appendChild(li.firstChild)
                }
                li.appendChild(p);
                first = p
              }
              var span = me.document.createElement("span");
              range.insertNode(span);
              domUtils.breakParent(span, li);
              var nextLi = span.nextSibling;
              first = nextLi.firstChild;
              if (!first) {
                p = me.document.createElement("p");
                domUtils.fillNode(me.document, p);
                nextLi.appendChild(p);
                first = p
              }
              if (domUtils.isEmptyNode(first)) {
                first.innerHTML = "";
                domUtils.fillNode(me.document, first)
              }
              range.setStart(first, 0).collapse(true).shrinkBoundary().select();
              domUtils.remove(span);
              var pre = nextLi.previousSibling;
              if (pre && domUtils.isEmptyBlock(pre)) {
                pre.innerHTML = "<p></p>";
                domUtils.fillNode(me.document, pre.firstChild)
              }
            }
            preventAndSave()
          }
        }
      }
      if (keyCode === 8) {
        range = me.selection.getRange();
        if (range.collapsed && domUtils.isStartInblock(range)) {
          tmpRange = range.cloneRange().trimBoundary();
          li = domUtils.findParentByTagName(range.startContainer, "li", true);
          if (li && domUtils.isStartInblock(tmpRange)) {
            start = domUtils.findParentByTagName(range.startContainer, "p", true);
            if (start && start !== li.firstChild) {
              var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]);
              domUtils.breakParent(start, parentList);
              clearEmptySibling(start);
              me.fireEvent("contentchange");
              range.setStart(start, 0).setCursor(false, true);
              me.fireEvent("saveScene");
              domUtils.preventDefault(evt);
              return
            }
            if (li && (pre = li.previousSibling)) {
              if (keyCode === 46 && li.childNodes.length) {
                return
              }
              if (dtd.$list[pre.tagName]) {
                pre = pre.lastChild
              }
              me.undoManger && me.undoManger.save();
              first = li.firstChild;
              if (domUtils.isBlockElm(first)) {
                if (domUtils.isEmptyNode(first)) {
                  pre.appendChild(first);
                  range.setStart(first, 0).setCursor(false, true);
                  while (li.firstChild) {
                    pre.appendChild(li.firstChild)
                  }
                } else {
                  span = me.document.createElement("span");
                  range.insertNode(span);
                  if (domUtils.isEmptyBlock(pre)) {
                    pre.innerHTML = ""
                  }
                  domUtils.moveChild(li, pre);
                  range.setStartBefore(span).collapse(true).select(true);
                  domUtils.remove(span)
                }
              } else {
                if (domUtils.isEmptyNode(li)) {
                  var p = me.document.createElement("p");
                  pre.appendChild(p);
                  range.setStart(p, 0).setCursor()
                } else {
                  range.setEnd(pre, pre.childNodes.length).collapse().select(true);
                  while (li.firstChild) {
                    pre.appendChild(li.firstChild)
                  }
                }
              }
              domUtils.remove(li);
              me.fireEvent("contentchange");
              me.fireEvent("saveScene");
              domUtils.preventDefault(evt);
              return
            }
            if (li && !li.previousSibling) {
              var parentList = li.parentNode;
              var bk = range.createBookmark();
              if (domUtils.isTagNode(parentList.parentNode, "ol ul")) {
                parentList.parentNode.insertBefore(li, parentList);
                if (domUtils.isEmptyNode(parentList)) {
                  domUtils.remove(parentList)
                }
              } else {
                while (li.firstChild) {
                  parentList.parentNode.insertBefore(li.firstChild, parentList)
                }
                domUtils.remove(li);
                if (domUtils.isEmptyNode(parentList)) {
                  domUtils.remove(parentList)
                }
              }
              range.moveToBookmark(bk).setCursor(false, true);
              me.fireEvent("contentchange");
              me.fireEvent("saveScene");
              domUtils.preventDefault(evt);
              return
            }
          }
        }
      }
    });
    me.addListener("keyup", function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 8) {
        var rng = me.selection.getRange(), list;
        if (list = domUtils.findParentByTagName(rng.startContainer, ["ol", "ul"], true)) {
          adjustList(list, list.tagName.toLowerCase(), getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"), true)
        }
      }
    });
    me.addListener("tabkeydown", function () {
      var range = me.selection.getRange();

      function checkLevel(li) {
        if (me.options.maxListLevel != -1) {
          var level = li.parentNode, levelNum = 0;
          while (/[ou]l/i.test(level.tagName)) {
            levelNum++;
            level = level.parentNode
          }
          if (levelNum >= me.options.maxListLevel) {
            return true
          }
        }
      }

      var li = domUtils.findParentByTagName(range.startContainer, "li", true);
      if (li) {
        var bk;
        if (range.collapsed) {
          if (checkLevel(li)) return true;
          var parentLi = li.parentNode, list = me.document.createElement(parentLi.tagName), index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi) || domUtils.getComputedStyle(parentLi, "list-style-type"));
          index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
          var currentStyle = listStyle[list.tagName][index];
          setListStyle(list, currentStyle);
          if (domUtils.isStartInblock(range)) {
            me.fireEvent("saveScene");
            bk = range.createBookmark();
            parentLi.insertBefore(list, li);
            list.appendChild(li);
            adjustList(list, list.tagName.toLowerCase(), currentStyle);
            me.fireEvent("contentchange");
            range.moveToBookmark(bk).select(true);
            return true
          }
        } else {
          me.fireEvent("saveScene");
          bk = range.createBookmark();
          for (var i = 0, closeList, parents = domUtils.findParents(li), ci; ci = parents[i++];) {
            if (domUtils.isTagNode(ci, "ol ul")) {
              closeList = ci;
              break
            }
          }
          var current = li;
          if (bk.end) {
            while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
              if (checkLevel(current)) {
                current = domUtils.getNextDomNode(current, false, null, function (node) {
                  return node !== closeList
                });
                continue
              }
              var parentLi = current.parentNode, list = me.document.createElement(parentLi.tagName), index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi) || domUtils.getComputedStyle(parentLi, "list-style-type"));
              var currentIndex = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
              var currentStyle = listStyle[list.tagName][currentIndex];
              setListStyle(list, currentStyle);
              parentLi.insertBefore(list, current);
              while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
                li = current.nextSibling;
                list.appendChild(current);
                if (!li || domUtils.isTagNode(li, "ol ul")) {
                  if (li) {
                    while (li = li.firstChild) {
                      if (li.tagName == "LI") {
                        break
                      }
                    }
                  } else {
                    li = domUtils.getNextDomNode(current, false, null, function (node) {
                      return node !== closeList
                    })
                  }
                  break
                }
                current = li
              }
              adjustList(list, list.tagName.toLowerCase(), currentStyle);
              current = li
            }
          }
          me.fireEvent("contentchange");
          range.moveToBookmark(bk).select();
          return true
        }
      }
    });

    function getLi(start) {
      while (start && !domUtils.isBody(start)) {
        if (start.nodeName == "TABLE") {
          return null
        }
        if (start.nodeName == "LI") {
          return start
        }
        start = start.parentNode
      }
    }

    me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = {
      execCommand: function (command, style) {
        if (!style) {
          style = command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc"
        }
        var me = this, range = this.selection.getRange(), filterFn = function (node) {
          return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" : !domUtils.isWhitespace(node)
        }, tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul", frag = me.document.createDocumentFragment();
        range.adjustmentBoundary().shrinkBoundary();
        var bko = range.createBookmark(true), start = getLi(me.document.getElementById(bko.start)), modifyStart = 0, end = getLi(me.document.getElementById(bko.end)), modifyEnd = 0, startParent, endParent, list, tmp;
        if (start || end) {
          start && (startParent = start.parentNode);
          if (!bko.end) {
            end = start
          }
          end && (endParent = end.parentNode);
          if (startParent === endParent) {
            while (start !== end) {
              tmp = start;
              start = start.nextSibling;
              if (!domUtils.isBlockElm(tmp.firstChild)) {
                var p = me.document.createElement("p");
                while (tmp.firstChild) {
                  p.appendChild(tmp.firstChild)
                }
                tmp.appendChild(p)
              }
              frag.appendChild(tmp)
            }
            tmp = me.document.createElement("span");
            startParent.insertBefore(tmp, end);
            if (!domUtils.isBlockElm(end.firstChild)) {
              p = me.document.createElement("p");
              while (end.firstChild) {
                p.appendChild(end.firstChild)
              }
              end.appendChild(p)
            }
            frag.appendChild(end);
            domUtils.breakParent(tmp, startParent);
            if (domUtils.isEmptyNode(tmp.previousSibling)) {
              domUtils.remove(tmp.previousSibling)
            }
            if (domUtils.isEmptyNode(tmp.nextSibling)) {
              domUtils.remove(tmp.nextSibling)
            }
            var nodeStyle = getStyle(startParent) || domUtils.getComputedStyle(startParent, "list-style-type") || (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc");
            if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
              for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); ci = frag.firstChild;) {
                if (domUtils.isTagNode(ci, "ol ul")) {
                  tmpFrag.appendChild(ci)
                } else {
                  while (ci.firstChild) {
                    tmpFrag.appendChild(ci.firstChild);
                    domUtils.remove(ci)
                  }
                }
              }
              tmp.parentNode.insertBefore(tmpFrag, tmp)
            } else {
              list = me.document.createElement(tag);
              setListStyle(list, style);
              list.appendChild(frag);
              tmp.parentNode.insertBefore(list, tmp)
            }
            domUtils.remove(tmp);
            list && adjustList(list, tag, style);
            range.moveToBookmark(bko).select();
            return
          }
          if (start) {
            while (start) {
              tmp = start.nextSibling;
              if (domUtils.isTagNode(start, "ol ul")) {
                frag.appendChild(start)
              } else {
                var tmpfrag = me.document.createDocumentFragment(), hasBlock = 0;
                while (start.firstChild) {
                  if (domUtils.isBlockElm(start.firstChild)) {
                    hasBlock = 1
                  }
                  tmpfrag.appendChild(start.firstChild)
                }
                if (!hasBlock) {
                  var tmpP = me.document.createElement("p");
                  tmpP.appendChild(tmpfrag);
                  frag.appendChild(tmpP)
                } else {
                  frag.appendChild(tmpfrag)
                }
                domUtils.remove(start)
              }
              start = tmp
            }
            startParent.parentNode.insertBefore(frag, startParent.nextSibling);
            if (domUtils.isEmptyNode(startParent)) {
              range.setStartBefore(startParent);
              domUtils.remove(startParent)
            } else {
              range.setStartAfter(startParent)
            }
            modifyStart = 1
          }
          if (end && domUtils.inDoc(endParent, me.document)) {
            start = endParent.firstChild;
            while (start && start !== end) {
              tmp = start.nextSibling;
              if (domUtils.isTagNode(start, "ol ul")) {
                frag.appendChild(start)
              } else {
                tmpfrag = me.document.createDocumentFragment();
                hasBlock = 0;
                while (start.firstChild) {
                  if (domUtils.isBlockElm(start.firstChild)) {
                    hasBlock = 1
                  }
                  tmpfrag.appendChild(start.firstChild)
                }
                if (!hasBlock) {
                  tmpP = me.document.createElement("p");
                  tmpP.appendChild(tmpfrag);
                  frag.appendChild(tmpP)
                } else {
                  frag.appendChild(tmpfrag)
                }
                domUtils.remove(start)
              }
              start = tmp
            }
            var tmpDiv = domUtils.createElement(me.document, "div", {tmpDiv: 1});
            domUtils.moveChild(end, tmpDiv);
            frag.appendChild(tmpDiv);
            domUtils.remove(end);
            endParent.parentNode.insertBefore(frag, endParent);
            range.setEndBefore(endParent);
            if (domUtils.isEmptyNode(endParent)) {
              domUtils.remove(endParent)
            }
            modifyEnd = 1
          }
        }
        if (!modifyStart) {
          range.setStartBefore(me.document.getElementById(bko.start))
        }
        if (bko.end && !modifyEnd) {
          range.setEndAfter(me.document.getElementById(bko.end))
        }
        range.enlarge(true, function (node) {
          return notExchange[node.tagName]
        });
        frag = me.document.createDocumentFragment();
        var bk = range.createBookmark(), current = domUtils.getNextDomNode(bk.start, false, filterFn), tmpRange = range.cloneRange(), tmpNode, block = domUtils.isBlockElm;
        while (current && current !== bk.end && domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING) {
          if (current.nodeType == 3 || dtd.li[current.tagName]) {
            if (current.nodeType == 1 && dtd.$list[current.tagName]) {
              while (current.firstChild) {
                frag.appendChild(current.firstChild)
              }
              tmpNode = domUtils.getNextDomNode(current, false, filterFn);
              domUtils.remove(current);
              current = tmpNode;
              continue
            }
            tmpNode = current;
            tmpRange.setStartBefore(current);
            while (current && current !== bk.end && (!block(current) || domUtils.isBookmarkNode(current))) {
              tmpNode = current;
              current = domUtils.getNextDomNode(current, false, null, function (node) {
                return !notExchange[node.tagName]
              })
            }
            if (current && block(current)) {
              tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
              if (tmp && domUtils.isBookmarkNode(tmp)) {
                current = domUtils.getNextDomNode(tmp, false, filterFn);
                tmpNode = tmp
              }
            }
            tmpRange.setEndAfter(tmpNode);
            current = domUtils.getNextDomNode(tmpNode, false, filterFn);
            var li = range.document.createElement("li");
            li.appendChild(tmpRange.extractContents());
            if (domUtils.isEmptyNode(li)) {
              var tmpNode = range.document.createElement("p");
              while (li.firstChild) {
                tmpNode.appendChild(li.firstChild)
              }
              li.appendChild(tmpNode)
            }
            frag.appendChild(li)
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn)
          }
        }
        range.moveToBookmark(bk).collapse(true);
        list = me.document.createElement(tag);
        setListStyle(list, style);
        list.appendChild(frag);
        range.insertNode(list);
        adjustList(list, tag, style);
        for (var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div"); ci = tmpDivs[i++];) {
          if (ci.getAttribute("tmpDiv")) {
            domUtils.remove(ci, true)
          }
        }
        range.moveToBookmark(bko).select()
      }, queryCommandState: function (command) {
        var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
        var path = this.selection.getStartElementPath();
        for (var i = 0, ci; ci = path[i++];) {
          if (ci.nodeName == "TABLE") {
            return 0
          }
          if (tag == ci.nodeName.toLowerCase()) {
            return 1
          }
        }
        return 0
      }, queryCommandValue: function (command) {
        var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
        var path = this.selection.getStartElementPath(), node;
        for (var i = 0, ci; ci = path[i++];) {
          if (ci.nodeName == "TABLE") {
            node = null;
            break
          }
          if (tag == ci.nodeName.toLowerCase()) {
            node = ci;
            break
          }
        }
        return node ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type") : null
      }
    }
  };
  (function () {
    var sourceEditors = {
      textarea: function (editor, holder) {
        var textarea = holder.ownerDocument.createElement("textarea");
        textarea.style.cssText = "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;";
        if (browser.ie && browser.version < 8) {
          textarea.style.width = holder.offsetWidth + "px";
          textarea.style.height = holder.offsetHeight + "px";
          holder.onresize = function () {
            textarea.style.width = holder.offsetWidth + "px";
            textarea.style.height = holder.offsetHeight + "px"
          }
        }
        holder.appendChild(textarea);
        return {
          setContent: function (content) {
            textarea.value = content
          }, getContent: function () {
            return textarea.value
          }, select: function () {
            var range;
            if (browser.ie) {
              range = textarea.createTextRange();
              range.collapse(true);
              range.select()
            } else {
              textarea.setSelectionRange(0, 0);
              textarea.focus()
            }
          }, dispose: function () {
            holder.removeChild(textarea);
            holder.onresize = null;
            textarea = null;
            holder = null
          }, focus: function () {
            textarea.focus()
          }, blur: function () {
            textarea.blur()
          }
        }
      }, codemirror: function (editor, holder) {
        var codeEditor = window.CodeMirror(holder, {
          mode: "text/html", tabMode: "indent", lineNumbers: true, lineWrapping: true, onChange: function (v) {
            editor.sync();
            editor.fireEvent("contentchange")
          }
        });
        var dom = codeEditor.getWrapperElement();
        dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;';
        codeEditor.getScrollerElement().style.cssText = "position:absolute;left:0;top:0;width:100%;height:100%;";
        codeEditor.refresh();
        return {
          getCodeMirror: function () {
            return codeEditor
          }, setContent: function (content) {
            codeEditor.setValue(content)
          }, getContent: function () {
            return codeEditor.getValue()
          }, select: function () {
            codeEditor.focus()
          }, dispose: function () {
            holder.removeChild(dom);
            dom = null;
            codeEditor = null
          }, focus: function () {
            codeEditor.focus()
          }, blur: function () {
            codeEditor.setOption("readOnly", true);
            codeEditor.setOption("readOnly", false)
          }
        }
      }
    };
    UE.plugins["source"] = function () {
      var me = this;
      var opt = this.options;
      var sourceMode = false;
      var sourceEditor;
      var orgSetContent;
      var orgFocus;
      var orgBlur;
      opt.sourceEditor = browser.ie ? "textarea" : opt.sourceEditor || "codemirror";
      me.setOpt({sourceEditorFirst: false});

      function createSourceEditor(holder) {
        return sourceEditors[opt.sourceEditor == "codemirror" && window.CodeMirror ? "codemirror" : "textarea"](me, holder)
      }

      var bakCssText;
      var oldGetContent, bakAddress;
      me.commands["source"] = {
        execCommand: function () {
          sourceMode = !sourceMode;
          if (sourceMode) {
            bakAddress = me.selection.getRange().createAddress(false, true);
            me.undoManger && me.undoManger.save(true);
            if (browser.gecko) {
              me.body.contentEditable = false
            }
            bakCssText = me.iframe.style.cssText;
            me.iframe.style.cssText += "position:absolute;left:-32768px;top:-32768px;";
            me.fireEvent("beforegetcontent");
            var root = UE.htmlparser(me.body.innerHTML);
            me.filterOutputRule(root);
            root.traversal(function (node) {
              if (node.type == "element") {
                switch (node.tagName) {
                  case"td":
                  case"th":
                  case"caption":
                    if (node.children && node.children.length == 1) {
                      if (node.firstChild().tagName == "br") {
                        node.removeChild(node.firstChild())
                      }
                    }
                    break;
                  case"pre":
                    node.innerText(node.innerText().replace(/&nbsp;/g, " "))
                }
              }
            });
            me.fireEvent("aftergetcontent");
            var content = root.toHtml(true);
            sourceEditor = createSourceEditor(me.iframe.parentNode);
            sourceEditor.setContent(content);
            orgSetContent = me.setContent;
            me.setContent = function (html) {
              var root = UE.htmlparser(html);
              me.filterInputRule(root);
              html = root.toHtml();
              sourceEditor.setContent(html)
            };
            setTimeout(function () {
              sourceEditor.select();
              me.addListener("fullscreenchanged", function () {
                try {
                  sourceEditor.getCodeMirror().refresh()
                } catch (e) {
                }
              })
            });
            oldGetContent = me.getContent;
            me.getContent = function () {
              return sourceEditor.getContent() || "<p>" + (browser.ie ? "" : "<br/>") + "</p>"
            };
            orgFocus = me.focus;
            orgBlur = me.blur;
            me.focus = function () {
              sourceEditor.focus()
            };
            me.blur = function () {
              orgBlur.call(me);
              sourceEditor.blur()
            }
          } else {
            me.iframe.style.cssText = bakCssText;
            var cont = sourceEditor.getContent() || "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
            cont = cont.replace(new RegExp("[\\r\\t\\n ]*</?(\\w+)\\s*(?:[^>]*)>", "g"), function (a, b) {
              if (b && !dtd.$inlineWithA[b.toLowerCase()]) {
                return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, "")
              }
              return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, "")
            });
            me.setContent = orgSetContent;
            me.setContent(cont);
            sourceEditor.dispose();
            sourceEditor = null;
            me.getContent = oldGetContent;
            me.focus = orgFocus;
            me.blur = orgBlur;
            var first = me.body.firstChild;
            if (!first) {
              me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
              first = me.body.firstChild
            }
            me.undoManger && me.undoManger.save(true);
            if (browser.gecko) {
              var input = document.createElement("input");
              input.style.cssText = "position:absolute;left:0;top:-32768px";
              document.body.appendChild(input);
              me.body.contentEditable = false;
              setTimeout(function () {
                domUtils.setViewportOffset(input, {left: -32768, top: 0});
                input.focus();
                setTimeout(function () {
                  me.body.contentEditable = true;
                  me.selection.getRange().moveToAddress(bakAddress).select(true);
                  domUtils.remove(input)
                })
              })
            } else {
              try {
                me.selection.getRange().moveToAddress(bakAddress).select(true)
              } catch (e) {
              }
            }
          }
          this.fireEvent("sourcemodechanged", sourceMode)
        }, queryCommandState: function () {
          return sourceMode | 0
        }, notNeedUndo: 1
      };
      var oldQueryCommandState = me.queryCommandState;
      me.queryCommandState = function (cmdName) {
        cmdName = cmdName.toLowerCase();
        if (sourceMode) {
          return cmdName in {source: 1, fullscreen: 1} ? 1 : -1
        }
        return oldQueryCommandState.apply(this, arguments)
      };
      if (opt.sourceEditor == "codemirror") {
        me.addListener("ready", function () {
          utils.loadFile(document, {src: opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js", tag: "script", type: "text/javascript", defer: "defer"}, function () {
            if (opt.sourceEditorFirst) {
              setTimeout(function () {
                me.execCommand("source")
              }, 0)
            }
          });
          utils.loadFile(document, {tag: "link", rel: "stylesheet", type: "text/css", href: opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css?221123"})
        })
      }
    }
  })();
  UE.plugins["enterkey"] = function () {
    var hTag, me = this, tag = me.options.enterTag;
    me.addListener("keyup", function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 13) {
        var range = me.selection.getRange(), start = range.startContainer, doSave;
        if (!browser.ie) {
          if (/h\d/i.test(hTag)) {
            if (browser.gecko) {
              var h = domUtils.findParentByTagName(start, ["h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "caption", "table"], true);
              if (!h) {
                me.document.execCommand("formatBlock", false, "<p>");
                doSave = 1
              }
            } else {
              if (start.nodeType == 1) {
                var tmp = me.document.createTextNode(""), div;
                range.insertNode(tmp);
                div = domUtils.findParentByTagName(tmp, "div", true);
                if (div) {
                  var p = me.document.createElement("p");
                  while (div.firstChild) {
                    p.appendChild(div.firstChild)
                  }
                  div.parentNode.insertBefore(p, div);
                  domUtils.remove(div);
                  range.setStartBefore(tmp).setCursor();
                  doSave = 1
                }
                domUtils.remove(tmp)
              }
            }
            if (me.undoManger && doSave) {
              me.undoManger.save()
            }
          }
          browser.opera && range.select()
        } else {
          me.fireEvent("saveScene", true, true)
        }
      }
    });
    me.addListener("keydown", function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 13) {
        if (me.fireEvent("beforeenterkeydown")) {
          domUtils.preventDefault(evt);
          return
        }
        me.fireEvent("saveScene", true, true);
        hTag = "";
        var range = me.selection.getRange();
        if (!range.collapsed) {
          var start = range.startContainer, end = range.endContainer, startTd = domUtils.findParentByTagName(start, "td", true), endTd = domUtils.findParentByTagName(end, "td", true);
          if (startTd && endTd && startTd !== endTd || !startTd && endTd || startTd && !endTd) {
            evt.preventDefault ? evt.preventDefault() : evt.returnValue = false;
            return
          }
        }
        if (tag == "p") {
          if (!browser.ie) {
            start = domUtils.findParentByTagName(range.startContainer, ["ol", "ul", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "caption"], true);
            if (!start && !browser.opera) {
              me.document.execCommand("formatBlock", false, "<p>");
              if (browser.gecko) {
                range = me.selection.getRange();
                start = domUtils.findParentByTagName(range.startContainer, "p", true);
                start && domUtils.removeDirtyAttr(start)
              }
            } else {
              hTag = start.tagName;
              start.tagName.toLowerCase() == "p" && browser.gecko && domUtils.removeDirtyAttr(start)
            }
          }
        } else {
          evt.preventDefault ? evt.preventDefault() : evt.returnValue = false;
          if (!range.collapsed) {
            range.deleteContents();
            start = range.startContainer;
            if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) {
              while (start.nodeType == 1) {
                if (dtd.$empty[start.tagName]) {
                  range.setStartBefore(start).setCursor();
                  if (me.undoManger) {
                    me.undoManger.save()
                  }
                  return false
                }
                if (!start.firstChild) {
                  var br = range.document.createElement("br");
                  start.appendChild(br);
                  range.setStart(start, 0).setCursor();
                  if (me.undoManger) {
                    me.undoManger.save()
                  }
                  return false
                }
                start = start.firstChild
              }
              if (start === range.startContainer.childNodes[range.startOffset]) {
                br = range.document.createElement("br");
                range.insertNode(br).setCursor()
              } else {
                range.setStart(start, 0).setCursor()
              }
            } else {
              br = range.document.createElement("br");
              range.insertNode(br).setStartAfter(br).setCursor()
            }
          } else {
            br = range.document.createElement("br");
            range.insertNode(br);
            var parent = br.parentNode;
            if (parent.lastChild === br) {
              br.parentNode.insertBefore(br.cloneNode(true), br);
              range.setStartBefore(br)
            } else {
              range.setStartAfter(br)
            }
            range.setCursor()
          }
        }
      }
    })
  };
  UE.plugins["keystrokes"] = function () {
    var me = this;
    var collapsed = true;
    me.addListener("keydown", function (type, evt) {
      var keyCode = evt.keyCode || evt.which, rng = me.selection.getRange();
      if (!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <= 90 || keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 111 || {13: 1, 8: 1, 46: 1}[keyCode])) {
        var tmpNode = rng.startContainer;
        if (domUtils.isFillChar(tmpNode)) {
          rng.setStartBefore(tmpNode)
        }
        tmpNode = rng.endContainer;
        if (domUtils.isFillChar(tmpNode)) {
          rng.setEndAfter(tmpNode)
        }
        rng.txtToElmBoundary();
        if (rng.endContainer && rng.endContainer.nodeType == 1) {
          tmpNode = rng.endContainer.childNodes[rng.endOffset];
          if (tmpNode && domUtils.isBr(tmpNode)) {
            rng.setEndAfter(tmpNode)
          }
        }
        if (rng.startOffset == 0) {
          tmpNode = rng.startContainer;
          if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
            tmpNode = rng.endContainer;
            if (rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode, "lastChild")) {
              me.fireEvent("saveScene");
              me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
              rng.setStart(me.body.firstChild, 0).setCursor(false, true);
              me._selectionChange();
              return
            }
          }
        }
      }
      if (keyCode == keymap.Backspace) {
        rng = me.selection.getRange();
        collapsed = rng.collapsed;
        if (me.fireEvent("delkeydown", evt)) {
          return
        }
        var start, end;
        if (rng.collapsed && rng.inFillChar()) {
          start = rng.startContainer;
          if (domUtils.isFillChar(start)) {
            rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
            domUtils.remove(start)
          } else {
            start.nodeValue = start.nodeValue.replace(new RegExp("^" + domUtils.fillChar), "");
            rng.startOffset--;
            rng.collapse(true).select(true)
          }
        }
        if (start = rng.getClosedNode()) {
          me.fireEvent("saveScene");
          rng.setStartBefore(start);
          domUtils.remove(start);
          rng.setCursor();
          me.fireEvent("saveScene");
          domUtils.preventDefault(evt);
          return
        }
        if (!browser.ie) {
          start = domUtils.findParentByTagName(rng.startContainer, "table", true);
          end = domUtils.findParentByTagName(rng.endContainer, "table", true);
          if (start && !end || !start && end || start !== end) {
            evt.preventDefault();
            return
          }
        }
      }
      if (keyCode == keymap.Tab) {
        var excludeTagNameForTabKey = {ol: 1, ul: 1, table: 1};
        if (me.fireEvent("tabkeydown", evt)) {
          domUtils.preventDefault(evt);
          return
        }
        var range = me.selection.getRange();
        me.fireEvent("saveScene");
        for (var i = 0, txt = "", tabSize = me.options.tabSize || 4, tabNode = me.options.tabNode || "&nbsp;"; i < tabSize; i++) {
          txt += tabNode
        }
        var span = me.document.createElement("span");
        span.innerHTML = txt + domUtils.fillChar;
        if (range.collapsed) {
          range.insertNode(span.cloneNode(true).firstChild).setCursor(true)
        } else {
          var filterFn = function (node) {
            return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]
          };
          start = domUtils.findParent(range.startContainer, filterFn, true);
          end = domUtils.findParent(range.endContainer, filterFn, true);
          if (start && end && start === end) {
            range.deleteContents();
            range.insertNode(span.cloneNode(true).firstChild).setCursor(true)
          } else {
            var bookmark = range.createBookmark();
            range.enlarge(true);
            var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
            while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
              current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
              current = domUtils.getNextDomNode(current, false, filterFn)
            }
            range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select()
          }
        }
        domUtils.preventDefault(evt)
      }
      if (browser.gecko && keyCode == 46) {
        range = me.selection.getRange();
        if (range.collapsed) {
          start = range.startContainer;
          if (domUtils.isEmptyBlock(start)) {
            var parent = start.parentNode;
            while (domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)) {
              start = parent;
              parent = parent.parentNode
            }
            if (start === parent.lastChild) evt.preventDefault();
            return
          }
        }
      }
      browser.chrome && me.on("keydown", function (type, e) {
        var keyCode = e.keyCode || e.which;
        if ((e.metaKey && e.altKey || e.ctrlKey && e.shiftKey) && keyCode == 73) {
          return true
        }
      })
    });
    me.addListener("keyup", function (type, evt) {
      var keyCode = evt.keyCode || evt.which, rng, me = this;
      if (keyCode == keymap.Backspace) {
        if (me.fireEvent("delkeyup")) {
          return
        }
        rng = me.selection.getRange();
        if (rng.collapsed) {
          var tmpNode, autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"];
          if (tmpNode = domUtils.findParentByTagName(rng.startContainer, autoClearTagName, true)) {
            if (domUtils.isEmptyBlock(tmpNode)) {
              var pre = tmpNode.previousSibling;
              if (pre && pre.nodeName != "TABLE") {
                domUtils.remove(tmpNode);
                rng.setStartAtLast(pre).setCursor(false, true);
                return
              } else {
                var next = tmpNode.nextSibling;
                if (next && next.nodeName != "TABLE") {
                  domUtils.remove(tmpNode);
                  rng.setStartAtFirst(next).setCursor(false, true);
                  return
                }
              }
            }
          }
          if (domUtils.isBody(rng.startContainer)) {
            var tmpNode = domUtils.createElement(me.document, "p", {innerHTML: browser.ie ? domUtils.fillChar : "<br/>"});
            rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true)
          }
        }
        if (!collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))) {
          if (browser.ie) {
            var span = rng.document.createElement("span");
            rng.insertNode(span).setStartBefore(span).collapse(true);
            rng.select();
            domUtils.remove(span)
          } else {
            rng.select()
          }
        }
      }
    })
  };
  UE.plugins["fiximgclick"] = function () {
    var elementUpdated = false;

    function Scale() {
      this.editor = null;
      this.resizer = null;
      this.cover = null;
      this.doc = document;
      this.prePos = {x: 0, y: 0};
      this.startPos = {x: 0, y: 0}
    }

    (function () {
      var rect = [[0, 0, -1, -1], [0, 0, 0, -1], [0, 0, 1, -1], [0, 0, -1, 0], [0, 0, 1, 0], [0, 0, -1, 1], [0, 0, 0, 1], [0, 0, 1, 1]];
      Scale.prototype = {
        init: function (editor) {
          var me = this;
          me.editor = editor;
          me.startPos = this.prePos = {x: 0, y: 0};
          me.dragId = -1;
          var hands = [], cover = me.cover = document.createElement("div"), resizer = me.resizer = document.createElement("div");
          cover.id = me.editor.ui.id + "_imagescale_cover";
          cover.style.cssText = "position:absolute;display:none;z-index:" + me.editor.options.zIndex + ";filter:alpha(opacity=0); opacity:0;background:#CCC;";
          domUtils.on(cover, "mousedown", function (e) {
            me.hide()
          });
          for (var i = 0; i < 8; i++) {
            hands.push('<span class="edui-editor-imagescale-hand' + i + '"></span>')
          }
          resizer.id = me.editor.ui.id + "_imagescale";
          resizer.className = "edui-editor-imagescale";
          resizer.innerHTML = hands.join("");
          resizer.style.cssText += ";display:none;border:1px solid #3b77ff;z-index:" + me.editor.options.zIndex + ";";
          me.editor.ui.getDom().appendChild(cover);
          me.editor.ui.getDom().appendChild(resizer);
          me.initStyle();
          me.initEvents()
        }, initStyle: function () {
          utils.cssRule("imagescale", ".edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}" + ".edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}")
        }, initEvents: function () {
          var me = this;
          me.startPos.x = me.startPos.y = 0;
          me.isDraging = false
        }, _eventHandler: function (e) {
          var me = this;
          switch (e.type) {
            case"mousedown":
              var hand = e.target || e.srcElement, hand;
              if (hand.className.indexOf("edui-editor-imagescale-hand") !== -1 && me.dragId === -1) {
                me.dragId = hand.className.slice(-1);
                me.startPos.x = me.prePos.x = e.clientX;
                me.startPos.y = me.prePos.y = e.clientY;
                domUtils.on(me.doc, "mousemove", me.proxy(me._eventHandler, me))
              }
              break;
            case"mousemove":
              if (me.dragId !== -1) {
                me.updateContainerStyle(me.dragId, {x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y});
                me.prePos.x = e.clientX;
                me.prePos.y = e.clientY;
                elementUpdated = true;
                me.updateTargetElement()
              }
              break;
            case"mouseup":
              if (me.dragId !== -1) {
                me.updateContainerStyle(me.dragId, {x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y});
                me.updateTargetElement();
                if (me.target.parentNode) {
                  me.attachTo(me.target)
                }
                me.dragId = -1
              }
              domUtils.un(me.doc, "mousemove", me.proxy(me._eventHandler, me));
              if (elementUpdated) {
                elementUpdated = false;
                me.editor.fireEvent("contentchange")
              }
              break;
            default:
              break
          }
        }, updateTargetElement: function () {
          var me = this;
          domUtils.setStyles(me.target, {width: me.resizer.style.width, height: me.resizer.style.height});
          me.target.width = parseInt(me.resizer.style.width);
          me.target.height = parseInt(me.resizer.style.height);
          me.attachTo(me.target)
        }, updateContainerStyle: function (dir, offset) {
          var me = this, dom = me.resizer, tmp;
          if (rect[dir][0] != 0) {
            tmp = parseInt(dom.style.left) + offset.x;
            dom.style.left = me._validScaledProp("left", tmp) + "px"
          }
          if (rect[dir][1] != 0) {
            tmp = parseInt(dom.style.top) + offset.y;
            dom.style.top = me._validScaledProp("top", tmp) + "px"
          }
          if (rect[dir][2] != 0) {
            tmp = dom.clientWidth + rect[dir][2] * offset.x;
            dom.style.width = me._validScaledProp("width", tmp) + "px"
          }
          if (rect[dir][3] != 0) {
            tmp = dom.clientHeight + rect[dir][3] * offset.y;
            dom.style.height = me._validScaledProp("height", tmp) + "px"
          }
        }, _validScaledProp: function (prop, value) {
          var ele = this.resizer, wrap = document;
          value = isNaN(value) ? 0 : value;
          switch (prop) {
            case"left":
              return value < 0 ? 0 : value + ele.clientWidth > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value;
            case"top":
              return value < 0 ? 0 : value + ele.clientHeight > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value;
            case"width":
              return value <= 0 ? 1 : value + ele.offsetLeft > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value;
            case"height":
              return value <= 0 ? 1 : value + ele.offsetTop > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value
          }
        }, hideCover: function () {
          this.cover.style.display = "none"
        }, showCover: function () {
          var me = this, editorPos = domUtils.getXY(me.editor.ui.getDom()), iframePos = domUtils.getXY(me.editor.iframe);
          domUtils.setStyles(me.cover, {width: me.editor.iframe.offsetWidth + "px", height: me.editor.iframe.offsetHeight + "px", top: iframePos.y - editorPos.y + "px", left: iframePos.x - editorPos.x + "px", position: "absolute", display: ""})
        }, show: function (targetObj) {
          var me = this;
          me.resizer.style.display = "block";
          if (targetObj) {
            me.attachTo(targetObj)
          }
          domUtils.on(this.resizer, "mousedown", me.proxy(me._eventHandler, me));
          domUtils.on(me.doc, "mouseup", me.proxy(me._eventHandler, me));
          me.showCover();
          me.editor.fireEvent("afterscaleshow", me);
          me.editor.fireEvent("saveScene")
        }, hide: function () {
          var me = this;
          me.hideCover();
          me.resizer.style.display = "none";
          domUtils.un(me.resizer, "mousedown", me.proxy(me._eventHandler, me));
          domUtils.un(me.doc, "mouseup", me.proxy(me._eventHandler, me));
          me.editor.fireEvent("afterscalehide", me)
        }, proxy: function (fn, context) {
          return function (e) {
            return fn.apply(context || this, arguments)
          }
        }, attachTo: function (targetObj) {
          var me = this, target = me.target = targetObj, resizer = this.resizer, imgPos = domUtils.getXY(target), iframePos = domUtils.getXY(me.editor.iframe), editorPos = domUtils.getXY(resizer.parentNode);
          domUtils.setStyles(resizer, {
            width: target.width + "px",
            height: target.height + "px",
            left: iframePos.x + imgPos.x - me.editor.getScrollLeft() - editorPos.x - parseInt(resizer.style.borderLeftWidth) + "px",
            top: iframePos.y + imgPos.y - me.editor.getScrollTop() - editorPos.y - parseInt(resizer.style.borderTopWidth) + "px"
          })
        }
      }
    })();
    return function () {
      var me = this, imageScale;
      me.setOpt("imageScaleEnabled", true);
      if (!browser.ie && me.options.imageScaleEnabled) {
        me.addListener("click", function (type, e) {
          var range = me.selection.getRange(), img = range.getClosedNode();
          if (img && img.tagName === "IMG" && me.body.contentEditable !== "false" && img === e.target) {
            if (img.getAttribute("anchorname") || domUtils.hasClass(img, "uep-loading") || domUtils.hasClass(img, "uep-loading-error")) {
              return
            }
            if (!imageScale) {
              imageScale = new Scale;
              imageScale.init(me);
              me.ui.getDom().appendChild(imageScale.resizer);
              var _keyDownHandler = function (e) {
                imageScale.hide();
                if (imageScale.target) {
                  me.selection.getRange().selectNode(imageScale.target).select()
                }
              }, _mouseDownHandler = function (e) {
                var ele = e.target || e.srcElement;
                if (ele && (ele.className === undefined || ele.className.indexOf("edui-editor-imagescale") === -1)) {
                  _keyDownHandler(e)
                }
              }, timer;
              me.addListener("afterscaleshow", function (e) {
                me.addListener("beforekeydown", _keyDownHandler);
                me.addListener("beforemousedown", _mouseDownHandler);
                domUtils.on(document, "keydown", _keyDownHandler);
                domUtils.on(document, "mousedown", _mouseDownHandler);
                me.selection.getNative().removeAllRanges()
              });
              me.addListener("afterscalehide", function (e) {
                me.removeListener("beforekeydown", _keyDownHandler);
                me.removeListener("beforemousedown", _mouseDownHandler);
                domUtils.un(document, "keydown", _keyDownHandler);
                domUtils.un(document, "mousedown", _mouseDownHandler);
                var target = imageScale.target;
                if (target.parentNode) {
                  me.selection.getRange().selectNode(target).select()
                }
              });
              domUtils.on(imageScale.resizer, "mousedown", function (e) {
                me.selection.getNative().removeAllRanges();
                var ele = e.target || e.srcElement;
                if (ele && ele.className.indexOf("edui-editor-imagescale-hand") === -1) {
                  timer = setTimeout(function () {
                    imageScale.hide();
                    if (imageScale.target) me.selection.getRange().selectNode(ele).select()
                  }, 200)
                }
              });
              domUtils.on(imageScale.resizer, "mouseup", function (e) {
                var ele = e.target || e.srcElement;
                if (ele && ele.className.indexOf("edui-editor-imagescale-hand") === -1) {
                  clearTimeout(timer)
                }
              })
            }
            imageScale.show(img)
          } else {
            if (imageScale && imageScale.resizer.style.display !== "none") {
              imageScale.hide()
            }
          }
        })
      }
      if (browser.webkit) {
        me.addListener("click", function (type, e) {
          if (e.target.tagName === "IMG" && me.body.contentEditable !== "false") {
            var range = new dom.Range(me.document);
            range.selectNode(e.target).select()
          }
        })
      }
    }
  }();
  UE.plugin.register("autolink", function () {
    var cont = 0;
    return !browser.ie ? {
      bindEvents: {
        reset: function () {
          cont = 0
        }, keydown: function (type, evt) {
          var me = this;
          var keyCode = evt.keyCode || evt.which;
          if (keyCode == 32 || keyCode == 13) {
            var sel = me.selection.getNative(), range = sel.getRangeAt(0).cloneRange(), offset, charCode;
            var start = range.startContainer;
            while (start.nodeType == 1 && range.startOffset > 0) {
              start = range.startContainer.childNodes[range.startOffset - 1];
              if (!start) {
                break
              }
              range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
              range.collapse(true);
              start = range.startContainer
            }
            do {
              if (range.startOffset == 0) {
                start = range.startContainer.previousSibling;
                while (start && start.nodeType == 1) {
                  start = start.lastChild
                }
                if (!start || domUtils.isFillChar(start)) {
                  break
                }
                offset = start.nodeValue.length
              } else {
                start = range.startContainer;
                offset = range.startOffset
              }
              range.setStart(start, offset - 1);
              charCode = range.toString().charCodeAt(0)
            } while (charCode != 160 && charCode != 32);
            if (range.toString().replace(new RegExp(domUtils.fillChar, "g"), "").match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) {
              while (range.toString().length) {
                if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) {
                  break
                }
                try {
                  range.setStart(range.startContainer, range.startOffset + 1)
                } catch (e) {
                  var start = range.startContainer;
                  while (!(next = start.nextSibling)) {
                    if (domUtils.isBody(start)) {
                      return
                    }
                    start = start.parentNode
                  }
                  range.setStart(next, 0)
                }
              }
              if (domUtils.findParentByTagName(range.startContainer, "a", true)) {
                return
              }
              var a = me.document.createElement("a"), text = me.document.createTextNode(" "), href;
              me.undoManger && me.undoManger.save();
              a.appendChild(range.extractContents());
              a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, "");
              href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar, "g"), "");
              href = /^(?:https?:\/\/)/gi.test(href) ? href : "http://" + href;
              a.setAttribute("_src", utils.html(href));
              a.href = utils.html(href);
              range.insertNode(a);
              a.parentNode.insertBefore(text, a.nextSibling);
              range.setStart(text, 0);
              range.collapse(true);
              sel.removeAllRanges();
              sel.addRange(range);
              me.undoManger && me.undoManger.save()
            }
          }
        }
      }
    } : {}
  }, function () {
    var keyCodes = {37: 1, 38: 1, 39: 1, 40: 1, 13: 1, 32: 1};

    function checkIsCludeLink(node) {
      if (node.nodeType == 3) {
        return null
      }
      if (node.nodeName == "A") {
        return node
      }
      var lastChild = node.lastChild;
      while (lastChild) {
        if (lastChild.nodeName == "A") {
          return lastChild
        }
        if (lastChild.nodeType == 3) {
          if (domUtils.isWhitespace(lastChild)) {
            lastChild = lastChild.previousSibling;
            continue
          }
          return null
        }
        lastChild = lastChild.lastChild
      }
    }

    browser.ie && this.addListener("keyup", function (cmd, evt) {
      var me = this, keyCode = evt.keyCode;
      if (keyCodes[keyCode]) {
        var rng = me.selection.getRange();
        var start = rng.startContainer;
        if (keyCode == 13) {
          while (start && !domUtils.isBody(start) && !domUtils.isBlockElm(start)) {
            start = start.parentNode
          }
          if (start && !domUtils.isBody(start) && start.nodeName == "P") {
            var pre = start.previousSibling;
            if (pre && pre.nodeType == 1) {
              var pre = checkIsCludeLink(pre);
              if (pre && !pre.getAttribute("_href")) {
                domUtils.remove(pre, true)
              }
            }
          }
        } else if (keyCode == 32) {
          if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) {
            start = start.previousSibling;
            if (start && start.nodeName == "A" && !start.getAttribute("_href")) {
              domUtils.remove(start, true)
            }
          }
        } else {
          start = domUtils.findParentByTagName(start, "a", true);
          if (start && !start.getAttribute("_href")) {
            var bk = rng.createBookmark();
            domUtils.remove(start, true);
            rng.moveToBookmark(bk).select(true)
          }
        }
      }
    })
  });
  UE.plugins["autoheight"] = function () {
    var me = this;
    me.autoHeightEnabled = me.options.autoHeightEnabled !== false;
    if (!me.autoHeightEnabled) {
      return
    }
    var bakOverflow, lastHeight = 0, options = me.options, currentHeight, timer;

    function adjustHeight() {
      var me = this;
      clearTimeout(timer);
      if (isFullscreen) return;
      if (!me.queryCommandState || me.queryCommandState && me.queryCommandState("source") != 1) {
        timer = setTimeout(function () {
          var node = me.body.lastChild;
          while (node && node.nodeType != 1) {
            node = node.previousSibling
          }
          if (node && node.nodeType == 1) {
            node.style.clear = "both";
            currentHeight = Math.max(domUtils.getXY(node).y + node.offsetHeight + 25, Math.max(options.minFrameHeight, options.initialFrameHeight));
            if (currentHeight !== lastHeight) {
              me.iframe.parentNode.style.transition = "width 0.3s, height 0.3s, easy-in-out";
              if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
                me.iframe.parentNode.style.height = currentHeight + "px"
              }
              me.body.style.height = currentHeight + "px";
              lastHeight = currentHeight
            }
            domUtils.removeStyle(node, "clear")
          }
        }, 50)
      }
    }

    var isFullscreen;
    me.addListener("fullscreenchanged", function (cmd, f) {
      isFullscreen = f
    });
    me.addListener("destroy", function () {
      domUtils.un(me.window, "scroll", fixedScrollTop);
      me.removeListener("contentchange afterinserthtml keyup mouseup", adjustHeight)
    });
    me.enableAutoHeight = function () {
      var me = this;
      if (!me.autoHeightEnabled) {
        return
      }
      var doc = me.document;
      me.autoHeightEnabled = true;
      bakOverflow = doc.body.style.overflowY;
      doc.body.style.overflowY = "hidden";
      me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight);
      setTimeout(function () {
        adjustHeight.call(me)
      }, browser.gecko ? 100 : 0);
      me.fireEvent("autoheightchanged", me.autoHeightEnabled)
    };
    me.disableAutoHeight = function () {
      me.body.style.overflowY = bakOverflow || "";
      me.removeListener("contentchange", adjustHeight);
      me.removeListener("keyup", adjustHeight);
      me.removeListener("mouseup", adjustHeight);
      me.autoHeightEnabled = false;
      me.fireEvent("autoheightchanged", me.autoHeightEnabled)
    };
    me.on("setHeight", function () {
      me.disableAutoHeight()
    });
    me.addListener("ready", function () {
      me.enableAutoHeight();
      var timer;
      domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? "dragover" : "drop", function () {
        clearTimeout(timer);
        timer = setTimeout(function () {
          adjustHeight.call(me)
        }, 100)
      });
      domUtils.on(me.window, "scroll", fixedScrollTop)
    });
    var lastScrollY;

    function fixedScrollTop() {
      if (!me.window) return;
      if (lastScrollY === null) {
        lastScrollY = me.window.scrollY
      } else if (me.window.scrollY == 0 && lastScrollY != 0) {
        me.window.scrollTo(0, 0);
        lastScrollY = null
      }
    }
  };
  UE.plugins["autofloat"] = function () {
    var me = this, lang = me.getLang();
    me.setOpt({topOffset: 0});
    var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false, topOffset = me.options.topOffset;
    if (!optsAutoFloatEnabled) {
      return
    }
    var uiUtils = UE.ui.uiUtils, LteIE6 = browser.ie && browser.version <= 6, quirks = browser.quirks;

    function checkHasUI() {
      if (!UE.ui) {
        alert(lang.autofloatMsg);
        return 0
      }
      return 1
    }

    function fixIE6FixedPos() {
      var docStyle = document.body.style;
      docStyle.backgroundImage = 'url("about:blank")';
      docStyle.backgroundAttachment = "fixed"
    }

    var bakCssText, placeHolder = document.createElement("div"), toolbarBox, orgTop, getPosition, flag = true;

    function setFloating() {
      var toobarBoxPos = domUtils.getXY(toolbarBox), origalFloat = domUtils.getComputedStyle(toolbarBox, "position"), origalLeft = domUtils.getComputedStyle(toolbarBox, "left");
      toolbarBox.style.width = toolbarBox.offsetWidth + "px";
      toolbarBox.style.zIndex = me.options.zIndex * 1 + 1;
      toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox);
      if (LteIE6 || quirks && browser.ie) {
        if (toolbarBox.style.position != "absolute") {
          toolbarBox.style.position = "absolute"
        }
        toolbarBox.style.top = (document.body.scrollTop || document.documentElement.scrollTop) - orgTop + topOffset + "px"
      } else {
        if (browser.ie7Compat && flag) {
          flag = false;
          toolbarBox.style.left = domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left + 2 + "px"
        }
        if (toolbarBox.style.position != "fixed") {
          toolbarBox.style.position = "fixed";
          toolbarBox.style.top = topOffset + "px";
          (origalFloat == "absolute" || origalFloat == "relative") && parseFloat(origalLeft) && (toolbarBox.style.left = toobarBoxPos.x + "px")
        }
      }
    }

    function unsetFloating() {
      flag = true;
      if (placeHolder.parentNode) {
        placeHolder.parentNode.removeChild(placeHolder)
      }
      toolbarBox.style.cssText = bakCssText
    }

    me.unsetFloating = unsetFloating;

    function updateFloating() {
      var rect3 = getPosition(me.container);
      var offset = me.options.toolbarTopOffset || 0;
      if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) {
        setFloating()
      } else {
        unsetFloating()
      }
    }

    var defer_updateFloating = utils.defer(function () {
      updateFloating()
    }, browser.ie ? 200 : 100, true);
    me.addListener("destroy", function () {
      domUtils.un(window, ["scroll", "resize"], updateFloating);
      me.removeListener("keydown", defer_updateFloating)
    });
    me.addListener("ready", function () {
      if (checkHasUI(me)) {
        if (!me.ui) {
          return
        }
        getPosition = uiUtils.getClientRect;
        toolbarBox = me.ui.getDom("toolbarbox");
        orgTop = getPosition(toolbarBox).top;
        bakCssText = toolbarBox.style.cssText;
        placeHolder.style.height = toolbarBox.offsetHeight + "px";
        if (LteIE6) {
          fixIE6FixedPos()
        }
        domUtils.on(window, ["scroll", "resize"], updateFloating);
        me.addListener("keydown", defer_updateFloating);
        me.addListener("beforefullscreenchange", function (t, enabled) {
          if (enabled) {
            unsetFloating()
          }
        });
        me.addListener("fullscreenchanged", function (t, enabled) {
          if (!enabled) {
            updateFloating()
          }
        });
        me.addListener("sourcemodechanged", function (t, enabled) {
          setTimeout(function () {
            updateFloating()
          }, 0)
        });
        me.addListener("clearDoc", function () {
          setTimeout(function () {
            updateFloating()
          }, 0)
        })
      }
    })
  };
  UE.plugins["video"] = function () {
    var me = this;

    function creatInsertStr(url, width, height, id, align, classname, type) {
      var str;
      switch (type) {
        case"iframe":
          str = '<iframe class="' + classname + '" ' + ' src="' + utils.html(url) + '" width="' + width + '" height="' + height + '"' + " frameborder=0 allowfullscreen>";
          break;
        case"image":
          str = "<img " + (id ? 'id="' + id + '"' : "") + ' width="' + width + '" height="' + height + '" _url="' + url + '" class="' + '"' + ' src="' + me.options.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif" style="background:url(' + me.options.UEDITOR_HOME_URL + "themes/default/images/videologo.gif) no-repeat center center; border:1px solid gray;" + (align ? "float:" + align + ";" : "") + '" />';
          break;
        case"embed":
          str = '<embed type="application/x-shockwave-flash" class="' + classname + '" pluginspage="http://www.macromedia.com/go/getflashplayer"' + ' src="' + utils.html(url) + '" width="' + width + '" height="' + height + '"' + (align ? ' style="float:' + align + '"' : "") + ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >';
          break;
        case"video":
          var ext = url.substr(url.lastIndexOf(".") + 1);
          if (ext == "ogv") ext = "ogg";
          str = "<video" + (id ? ' id="' + id + '"' : "") + ' class="' + classname + '" ' + (align ? ' style="float:' + align + '"' : "") + ' controls preload="none" width="' + width + '" height="' + height + '" src="' + url + '" data-setup="{}">' + '<source src="' + url + '" type="video/' + ext + '" /></video>';
          break
      }
      return str
    }

    function switchImgAndVideo(root, img2video) {
      utils.each(root.getNodesByTagName(img2video ? "img" : "embed video"), function (node) {
        var className = node.getAttr("class");
        if (className && className.indexOf("edui-faked-video") != -1) {
          var html = creatInsertStr(img2video ? node.getAttr("_url") : node.getAttr("src"), node.getAttr("width"), node.getAttr("height"), null, node.getStyle("float") || "", className, img2video ? "embed" : "image");
          node.parentNode.replaceChild(UE.uNode.createElement(html), node)
        }
        if (className && className.indexOf("edui-upload-video") != -1) {
          var html = creatInsertStr(img2video ? node.getAttr("_url") : node.getAttr("src"), node.getAttr("width"), node.getAttr("height"), null, node.getStyle("float") || "", className, img2video ? "video" : "image");
          node.parentNode.replaceChild(UE.uNode.createElement(html), node)
        }
      })
    }

    me.addOutputRule(function (root) {
      switchImgAndVideo(root, true)
    });
    me.addInputRule(function (root) {
      switchImgAndVideo(root)
    });
    me.commands["insertvideo"] = {
      execCommand: function (cmd, videoObjs, type) {
        videoObjs = utils.isArray(videoObjs) ? videoObjs : [videoObjs];
        if (me.fireEvent("beforeinsertvideo", videoObjs) === true) {
          return
        }
        var html = [], id = "tmpVideo", cl;
        for (var i = 0, vi, len = videoObjs.length; i < len; i++) {
          vi = videoObjs[i];
          var videoType = "iframe";
          if (vi.url.match(/.mp4$/)) {
            videoType = "video"
          }
          cl = videoType == "iframe" ? "edui-video-iframe" : "edui-video-video";
          html.push(creatInsertStr(vi.url, vi.width || 420, vi.height || 280, id + i, null, cl, videoType))
        }
        me.execCommand("inserthtml", html.join(""), true);
        var rng = this.selection.getRange();
        me.fireEvent("afterinsertvideo", videoObjs)
      }, queryCommandState: function () {
        var img = me.selection.getRange().getClosedNode(),
          flag = img && (img.className == "edui-video-iframe" || img.className.indexOf("edui-video-iframe") != -1 || img.className == "edui-video-video" || img.className.indexOf("edui-video-video") != -1);
        return flag ? 1 : 0
      }
    }
  };
  UE.plugins["audio"] = function () {
    var me = this;

    function createAudioHtml(url, param) {
      param = param || {};
      var str = ["<audio", param.id ? ' id="' + param.id + '"' : "", param.cls ? ' class="' + param.cls + '"' : "", " controls >", '<source src="' + url + '" type="audio/mpeg' + '" />', "</audio>"];
      return str.join("")
    }

    function switchImgAndAudio(root, img2audio) {
    }

    me.addOutputRule(function (root) {
      switchImgAndAudio(root, true)
    });
    me.addInputRule(function (root) {
      switchImgAndAudio(root)
    });
    me.commands["insertaudio"] = {
      execCommand: function (cmd, audioObjs, type) {
        audioObjs = utils.isArray(audioObjs) ? audioObjs : [audioObjs];
        if (me.fireEvent("beforeinsertaudio", audioObjs) === true) {
          return
        }
        var html = [];
        for (var i = 0, vi, len = audioObjs.length; i < len; i++) {
          vi = audioObjs[i];
          html.push(createAudioHtml(vi.url, {cls: "edui-audio-audio"}))
        }
        me.execCommand("inserthtml", html.join(""), true);
        var rng = this.selection.getRange();
        me.fireEvent("afterinsertaudio", audioObjs)
      }, queryCommandState: function () {
        var img = me.selection.getRange().getClosedNode(), flag = img && (img.className == "edui-audio-audio" || img.className.indexOf("edui-audio-audio") != -1);
        return flag ? 1 : 0
      }
    }
  };
  (function () {
    var UETable = UE.UETable = function (table) {
      this.table = table;
      this.indexTable = [];
      this.selectedTds = [];
      this.cellsRange = {};
      this.update(table)
    };
    UETable.removeSelectedClass = function (cells) {
      utils.each(cells, function (cell) {
        domUtils.removeClasses(cell, "selectTdClass")
      })
    };
    UETable.addSelectedClass = function (cells) {
      utils.each(cells, function (cell) {
        domUtils.addClass(cell, "selectTdClass")
      })
    };
    UETable.isEmptyBlock = function (node) {
      var reg = new RegExp(domUtils.fillChar, "g");
      if (node[browser.ie ? "innerText" : "textContent"].replace(/^\s*$/, "").replace(reg, "").length > 0) {
        return 0
      }
      for (var i in dtd.$isNotEmpty) if (dtd.$isNotEmpty.hasOwnProperty(i)) {
        if (node.getElementsByTagName(i).length) {
          return 0
        }
      }
      return 1
    };
    UETable.getWidth = function (cell) {
      if (!cell) return 0;
      return parseInt(domUtils.getComputedStyle(cell, "width"), 10)
    };
    UETable.getTableCellAlignState = function (cells) {
      !utils.isArray(cells) && (cells = [cells]);
      var result = {}, status = ["align", "valign"], tempStatus = null, isSame = true;
      utils.each(cells, function (cellNode) {
        utils.each(status, function (currentState) {
          tempStatus = cellNode.getAttribute(currentState);
          if (!result[currentState] && tempStatus) {
            result[currentState] = tempStatus
          } else if (!result[currentState] || tempStatus !== result[currentState]) {
            isSame = false;
            return false
          }
        });
        return isSame
      });
      return isSame ? result : null
    };
    UETable.getTableItemsByRange = function (editor) {
      var start = editor.selection.getStart();
      if (start && start.id && start.id.indexOf("_baidu_bookmark_start_") === 0 && start.nextSibling) {
        start = start.nextSibling
      }
      var cell = start && domUtils.findParentByTagName(start, ["td", "th"], true), tr = cell && cell.parentNode, table = tr && domUtils.findParentByTagName(tr, ["table"]), caption = table && table.getElementsByTagName("caption")[0];
      return {cell: cell, tr: tr, table: table, caption: caption}
    };
    UETable.getUETableBySelected = function (editor) {
      var table = UETable.getTableItemsByRange(editor).table;
      if (table && table.ueTable && table.ueTable.selectedTds.length) {
        return table.ueTable
      }
      return null
    };
    UETable.getDefaultValue = function (editor, table) {
      var borderMap = {thin: "0px", medium: "1px", thick: "2px"}, tableBorder, tdPadding, tdBorder, tmpValue;
      if (!table) {
        table = editor.document.createElement("table");
        table.insertRow(0).insertCell(0).innerHTML = "xxx";
        editor.body.appendChild(table);
        var td = table.getElementsByTagName("td")[0];
        tmpValue = domUtils.getComputedStyle(table, "border-left-width");
        tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, "padding-left");
        tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, "border-left-width");
        tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        domUtils.remove(table);
        return {tableBorder: tableBorder, tdPadding: tdPadding, tdBorder: tdBorder}
      } else {
        td = table.getElementsByTagName("td")[0];
        tmpValue = domUtils.getComputedStyle(table, "border-left-width");
        tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, "padding-left");
        tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, "border-left-width");
        tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        return {tableBorder: tableBorder, tdPadding: tdPadding, tdBorder: tdBorder}
      }
    };
    UETable.getUETable = function (tdOrTable) {
      var tag = tdOrTable.tagName.toLowerCase();
      tdOrTable = tag == "td" || tag == "th" || tag == "caption" ? domUtils.findParentByTagName(tdOrTable, "table", true) : tdOrTable;
      if (!tdOrTable.ueTable) {
        tdOrTable.ueTable = new UETable(tdOrTable)
      }
      return tdOrTable.ueTable
    };
    UETable.cloneCell = function (cell, ignoreMerge, keepPro) {
      if (!cell || utils.isString(cell)) {
        return this.table.ownerDocument.createElement(cell || "td")
      }
      var flag = domUtils.hasClass(cell, "selectTdClass");
      flag && domUtils.removeClasses(cell, "selectTdClass");
      var tmpCell = cell.cloneNode(true);
      if (ignoreMerge) {
        tmpCell.rowSpan = tmpCell.colSpan = 1
      }
      !keepPro && domUtils.removeAttributes(tmpCell, "width height");
      !keepPro && domUtils.removeAttributes(tmpCell, "style");
      tmpCell.style.borderLeftStyle = "";
      tmpCell.style.borderTopStyle = "";
      tmpCell.style.borderLeftColor = cell.style.borderRightColor;
      tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;
      tmpCell.style.borderTopColor = cell.style.borderBottomColor;
      tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;
      flag && domUtils.addClass(cell, "selectTdClass");
      return tmpCell
    };
    UETable.prototype = {
      getMaxRows: function () {
        var rows = this.table.rows, maxLen = 1;
        for (var i = 0, row; row = rows[i]; i++) {
          var currentMax = 1;
          for (var j = 0, cj; cj = row.cells[j++];) {
            currentMax = Math.max(cj.rowSpan || 1, currentMax)
          }
          maxLen = Math.max(currentMax + i, maxLen)
        }
        return maxLen
      }, getMaxCols: function () {
        var rows = this.table.rows, maxLen = 0, cellRows = {};
        for (var i = 0, row; row = rows[i]; i++) {
          var cellsNum = 0;
          for (var j = 0, cj; cj = row.cells[j++];) {
            cellsNum += cj.colSpan || 1;
            if (cj.rowSpan && cj.rowSpan > 1) {
              for (var k = 1; k < cj.rowSpan; k++) {
                if (!cellRows["row_" + (i + k)]) {
                  cellRows["row_" + (i + k)] = cj.colSpan || 1
                } else {
                  cellRows["row_" + (i + k)]++
                }
              }
            }
          }
          cellsNum += cellRows["row_" + i] || 0;
          maxLen = Math.max(cellsNum, maxLen)
        }
        return maxLen
      }, getCellColIndex: function (cell) {
      }, getHSideCell: function (cell, right) {
        try {
          var cellInfo = this.getCellInfo(cell), previewRowIndex, previewColIndex;
          var len = this.selectedTds.length, range = this.cellsRange;
          if (!right && (!len ? !cellInfo.colIndex : !range.beginColIndex) || right && (!len ? cellInfo.colIndex == this.colsNum - 1 : range.endColIndex == this.colsNum - 1)) return null;
          previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;
          previewColIndex = !right ? !len ? cellInfo.colIndex < 1 ? 0 : cellInfo.colIndex - 1 : range.beginColIndex - 1 : !len ? cellInfo.colIndex + 1 : range.endColIndex + 1;
          return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex)
        } catch (e) {
          showError(e)
        }
      }, getTabNextCell: function (cell, preRowIndex) {
        var cellInfo = this.getCellInfo(cell), rowIndex = preRowIndex || cellInfo.rowIndex, colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1), nextCell;
        try {
          nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex)
        } catch (e) {
          try {
            rowIndex = rowIndex * 1 + 1;
            colIndex = 0;
            nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex)
          } catch (e) {
          }
        }
        return nextCell
      }, getVSideCell: function (cell, bottom, ignoreRange) {
        try {
          var cellInfo = this.getCellInfo(cell), nextRowIndex, nextColIndex;
          var len = this.selectedTds.length && !ignoreRange, range = this.cellsRange;
          if (!bottom && cellInfo.rowIndex == 0 || bottom && (!len ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1 : range.endRowIndex == this.rowsNum - 1)) return null;
          nextRowIndex = !bottom ? !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1 : !len ? cellInfo.rowIndex + cellInfo.rowSpan : range.endRowIndex + 1;
          nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
          return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex)
        } catch (e) {
          showError(e)
        }
      }, getSameEndPosCells: function (cell, xOrY) {
        try {
          var flag = xOrY.toLowerCase() === "x", end = domUtils.getXY(cell)[flag ? "x" : "y"] + cell["offset" + (flag ? "Width" : "Height")], rows = this.table.rows, cells = null, returns = [];
          for (var i = 0; i < this.rowsNum; i++) {
            cells = rows[i].cells;
            for (var j = 0, tmpCell; tmpCell = cells[j++];) {
              var tmpEnd = domUtils.getXY(tmpCell)[flag ? "x" : "y"] + tmpCell["offset" + (flag ? "Width" : "Height")];
              if (tmpEnd > end && flag) break;
              if (cell == tmpCell || end == tmpEnd) {
                if (tmpCell[flag ? "colSpan" : "rowSpan"] == 1) {
                  returns.push(tmpCell)
                }
                if (flag) break
              }
            }
          }
          return returns
        } catch (e) {
          showError(e)
        }
      }, setCellContent: function (cell, content) {
        cell.innerHTML = content || (browser.ie ? domUtils.fillChar : "<br />")
      }, cloneCell: UETable.cloneCell, getSameStartPosXCells: function (cell) {
        try {
          var start = domUtils.getXY(cell).x + cell.offsetWidth, rows = this.table.rows, cells, returns = [];
          for (var i = 0; i < this.rowsNum; i++) {
            cells = rows[i].cells;
            for (var j = 0, tmpCell; tmpCell = cells[j++];) {
              var tmpStart = domUtils.getXY(tmpCell).x;
              if (tmpStart > start) break;
              if (tmpStart == start && tmpCell.colSpan == 1) {
                returns.push(tmpCell);
                break
              }
            }
          }
          return returns
        } catch (e) {
          showError(e)
        }
      }, update: function (table) {
        this.table = table || this.table;
        this.selectedTds = [];
        this.cellsRange = {};
        this.indexTable = [];
        var rows = this.table.rows, rowsNum = this.getMaxRows(), dNum = rowsNum - rows.length, colsNum = this.getMaxCols();
        while (dNum--) {
          this.table.insertRow(rows.length)
        }
        this.rowsNum = rowsNum;
        this.colsNum = colsNum;
        for (var i = 0, len = rows.length; i < len; i++) {
          this.indexTable[i] = new Array(colsNum)
        }
        for (var rowIndex = 0, row; row = rows[rowIndex]; rowIndex++) {
          for (var cellIndex = 0, cell, cells = row.cells; cell = cells[cellIndex]; cellIndex++) {
            if (cell.rowSpan > rowsNum) {
              cell.rowSpan = rowsNum
            }
            var colIndex = cellIndex, rowSpan = cell.rowSpan || 1, colSpan = cell.colSpan || 1;
            while (this.indexTable[rowIndex][colIndex]) colIndex++;
            for (var j = 0; j < rowSpan; j++) {
              for (var k = 0; k < colSpan; k++) {
                this.indexTable[rowIndex + j][colIndex + k] = {rowIndex: rowIndex, cellIndex: cellIndex, colIndex: colIndex, rowSpan: rowSpan, colSpan: colSpan}
              }
            }
          }
        }
        for (j = 0; j < rowsNum; j++) {
          for (k = 0; k < colsNum; k++) {
            if (this.indexTable[j][k] === undefined) {
              row = rows[j];
              cell = row.cells[row.cells.length - 1];
              cell = cell ? cell.cloneNode(true) : this.table.ownerDocument.createElement("td");
              this.setCellContent(cell);
              if (cell.colSpan !== 1) cell.colSpan = 1;
              if (cell.rowSpan !== 1) cell.rowSpan = 1;
              row.appendChild(cell);
              this.indexTable[j][k] = {rowIndex: j, cellIndex: cell.cellIndex, colIndex: k, rowSpan: 1, colSpan: 1}
            }
          }
        }
        var tds = domUtils.getElementsByTagName(this.table, "td"), selectTds = [];
        utils.each(tds, function (td) {
          if (domUtils.hasClass(td, "selectTdClass")) {
            selectTds.push(td)
          }
        });
        if (selectTds.length) {
          var start = selectTds[0], end = selectTds[selectTds.length - 1], startInfo = this.getCellInfo(start), endInfo = this.getCellInfo(end);
          this.selectedTds = selectTds;
          this.cellsRange = {beginRowIndex: startInfo.rowIndex, beginColIndex: startInfo.colIndex, endRowIndex: endInfo.rowIndex + endInfo.rowSpan - 1, endColIndex: endInfo.colIndex + endInfo.colSpan - 1}
        }
        if (!domUtils.hasClass(this.table.rows[0], "firstRow")) {
          domUtils.addClass(this.table.rows[0], "firstRow");
          for (var i = 1; i < this.table.rows.length; i++) {
            domUtils.removeClasses(this.table.rows[i], "firstRow")
          }
        }
      }, getCellInfo: function (cell) {
        if (!cell) return;
        var cellIndex = cell.cellIndex, rowIndex = cell.parentNode.rowIndex, rowInfo = this.indexTable[rowIndex], numCols = this.colsNum;
        for (var colIndex = cellIndex; colIndex < numCols; colIndex++) {
          var cellInfo = rowInfo[colIndex];
          if (cellInfo.rowIndex === rowIndex && cellInfo.cellIndex === cellIndex) {
            return cellInfo
          }
        }
      }, getCell: function (rowIndex, cellIndex) {
        return rowIndex < this.rowsNum && this.table.rows[rowIndex].cells[cellIndex] || null
      }, deleteCell: function (cell, rowIndex) {
        rowIndex = typeof rowIndex == "number" ? rowIndex : cell.parentNode.rowIndex;
        var row = this.table.rows[rowIndex];
        row.deleteCell(cell.cellIndex)
      }, getCellsRange: function (cellA, cellB) {
        function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) {
          var tmpBeginRowIndex = beginRowIndex, tmpBeginColIndex = beginColIndex, tmpEndRowIndex = endRowIndex, tmpEndColIndex = endColIndex, cellInfo, colIndex, rowIndex;
          if (beginRowIndex > 0) {
            for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
              cellInfo = me.indexTable[beginRowIndex][colIndex];
              rowIndex = cellInfo.rowIndex;
              if (rowIndex < beginRowIndex) {
                tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex)
              }
            }
          }
          if (endColIndex < me.colsNum) {
            for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
              cellInfo = me.indexTable[rowIndex][endColIndex];
              colIndex = cellInfo.colIndex + cellInfo.colSpan - 1;
              if (colIndex > endColIndex) {
                tmpEndColIndex = Math.max(colIndex, tmpEndColIndex)
              }
            }
          }
          if (endRowIndex < me.rowsNum) {
            for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
              cellInfo = me.indexTable[endRowIndex][colIndex];
              rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1;
              if (rowIndex > endRowIndex) {
                tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex)
              }
            }
          }
          if (beginColIndex > 0) {
            for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
              cellInfo = me.indexTable[rowIndex][beginColIndex];
              colIndex = cellInfo.colIndex;
              if (colIndex < beginColIndex) {
                tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex)
              }
            }
          }
          if (tmpBeginRowIndex != beginRowIndex || tmpBeginColIndex != beginColIndex || tmpEndRowIndex != endRowIndex || tmpEndColIndex != endColIndex) {
            return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex)
          } else {
            return {beginRowIndex: beginRowIndex, beginColIndex: beginColIndex, endRowIndex: endRowIndex, endColIndex: endColIndex}
          }
        }

        try {
          var me = this, cellAInfo = me.getCellInfo(cellA);
          if (cellA === cellB) {
            return {beginRowIndex: cellAInfo.rowIndex, beginColIndex: cellAInfo.colIndex, endRowIndex: cellAInfo.rowIndex + cellAInfo.rowSpan - 1, endColIndex: cellAInfo.colIndex + cellAInfo.colSpan - 1}
          }
          var cellBInfo = me.getCellInfo(cellB);
          var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex), beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex),
            endRowIndex = Math.max(cellAInfo.rowIndex + cellAInfo.rowSpan - 1, cellBInfo.rowIndex + cellBInfo.rowSpan - 1), endColIndex = Math.max(cellAInfo.colIndex + cellAInfo.colSpan - 1, cellBInfo.colIndex + cellBInfo.colSpan - 1);
          return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex)
        } catch (e) {
        }
      }, getCells: function (range) {
        this.clearSelected();
        var beginRowIndex = range.beginRowIndex, beginColIndex = range.beginColIndex, endRowIndex = range.endRowIndex, endColIndex = range.endColIndex, cellInfo, rowIndex, colIndex, tdHash = {}, returnTds = [];
        for (var i = beginRowIndex; i <= endRowIndex; i++) {
          for (var j = beginColIndex; j <= endColIndex; j++) {
            cellInfo = this.indexTable[i][j];
            rowIndex = cellInfo.rowIndex;
            colIndex = cellInfo.colIndex;
            var key = rowIndex + "|" + colIndex;
            if (tdHash[key]) continue;
            tdHash[key] = 1;
            if (rowIndex < i || colIndex < j || rowIndex + cellInfo.rowSpan - 1 > endRowIndex || colIndex + cellInfo.colSpan - 1 > endColIndex) {
              return null
            }
            returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex))
          }
        }
        return returnTds
      }, clearSelected: function () {
        UETable.removeSelectedClass(this.selectedTds);
        this.selectedTds = [];
        this.cellsRange = {}
      }, setSelected: function (range) {
        var cells = this.getCells(range);
        UETable.addSelectedClass(cells);
        this.selectedTds = cells;
        this.cellsRange = range
      }, isFullRow: function () {
        var range = this.cellsRange;
        return range.endColIndex - range.beginColIndex + 1 == this.colsNum
      }, isFullCol: function () {
        var range = this.cellsRange, table = this.table, ths = table.getElementsByTagName("th"), rows = range.endRowIndex - range.beginRowIndex + 1;
        return !ths.length ? rows == this.rowsNum : rows == this.rowsNum || rows == this.rowsNum - 1
      }, getNextCell: function (cell, bottom, ignoreRange) {
        try {
          var cellInfo = this.getCellInfo(cell), nextRowIndex, nextColIndex;
          var len = this.selectedTds.length && !ignoreRange, range = this.cellsRange;
          if (!bottom && cellInfo.rowIndex == 0 || bottom && (!len ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1 : range.endRowIndex == this.rowsNum - 1)) return null;
          nextRowIndex = !bottom ? !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1 : !len ? cellInfo.rowIndex + cellInfo.rowSpan : range.endRowIndex + 1;
          nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
          return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex)
        } catch (e) {
          showError(e)
        }
      }, getPreviewCell: function (cell, top) {
        try {
          var cellInfo = this.getCellInfo(cell), previewRowIndex, previewColIndex;
          var len = this.selectedTds.length, range = this.cellsRange;
          if (!top && (!len ? !cellInfo.colIndex : !range.beginColIndex) || top && (!len ? cellInfo.rowIndex > this.colsNum - 1 : range.endColIndex == this.colsNum - 1)) return null;
          previewRowIndex = !top ? !len ? cellInfo.rowIndex : range.beginRowIndex : !len ? cellInfo.rowIndex < 1 ? 0 : cellInfo.rowIndex - 1 : range.beginRowIndex;
          previewColIndex = !top ? !len ? cellInfo.colIndex < 1 ? 0 : cellInfo.colIndex - 1 : range.beginColIndex - 1 : !len ? cellInfo.colIndex : range.endColIndex + 1;
          return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex)
        } catch (e) {
          showError(e)
        }
      }, moveContent: function (cellTo, cellFrom) {
        if (UETable.isEmptyBlock(cellFrom)) return;
        if (UETable.isEmptyBlock(cellTo)) {
          cellTo.innerHTML = cellFrom.innerHTML;
          return
        }
        var child = cellTo.lastChild;
        if (child.nodeType == 3 || !dtd.$block[child.tagName]) {
          cellTo.appendChild(cellTo.ownerDocument.createElement("br"))
        }
        while (child = cellFrom.firstChild) {
          cellTo.appendChild(child)
        }
      }, mergeRight: function (cell) {
        var cellInfo = this.getCellInfo(cell), rightColIndex = cellInfo.colIndex + cellInfo.colSpan, rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex], rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex);
        cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan;
        cell.removeAttribute("width");
        this.moveContent(cell, rightCell);
        this.deleteCell(rightCell, rightCellInfo.rowIndex);
        this.update()
      }, mergeDown: function (cell) {
        var cellInfo = this.getCellInfo(cell), downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan, downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex], downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex);
        cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan;
        cell.removeAttribute("height");
        this.moveContent(cell, downCell);
        this.deleteCell(downCell, downCellInfo.rowIndex);
        this.update()
      }, mergeRange: function () {
        var range = this.cellsRange, leftTopCell = this.getCell(range.beginRowIndex, this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex);
        var cells = this.getCells(range);
        for (var i = 0, ci; ci = cells[i++];) {
          if (ci !== leftTopCell) {
            this.moveContent(leftTopCell, ci);
            this.deleteCell(ci)
          }
        }
        leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1;
        leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute("height");
        leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1;
        leftTopCell.colSpan > 1 && leftTopCell.removeAttribute("width");
        if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) {
          leftTopCell.colSpan = 1
        }
        if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) {
          var rowIndex = leftTopCell.parentNode.rowIndex;
          if (this.table.deleteRow) {
            for (var i = rowIndex + 1, curIndex = rowIndex + 1, len = leftTopCell.rowSpan; i < len; i++) {
              this.table.deleteRow(curIndex)
            }
          } else {
            for (var i = 0, len = leftTopCell.rowSpan - 1; i < len; i++) {
              var row = this.table.rows[rowIndex + 1];
              row.parentNode.removeChild(row)
            }
          }
          leftTopCell.rowSpan = 1
        }
        this.update()
      }, insertRow: function (rowIndex, sourceCell) {
        var numCols = this.colsNum, table = this.table, row = table.insertRow(rowIndex), cell, thead = null, isInsertTitle = typeof sourceCell == "string" && sourceCell.toUpperCase() == "TH";

        function replaceTdToTh(colIndex, cell, tableRow) {
          if (colIndex == 0) {
            var tr = tableRow.nextSibling || tableRow.previousSibling, th = tr.cells[colIndex];
            if (th.tagName == "TH") {
              th = cell.ownerDocument.createElement("th");
              th.appendChild(cell.firstChild);
              tableRow.insertBefore(th, cell);
              domUtils.remove(cell)
            }
          } else {
            if (cell.tagName == "TH") {
              var td = cell.ownerDocument.createElement("td");
              td.appendChild(cell.firstChild);
              tableRow.insertBefore(td, cell);
              domUtils.remove(cell)
            }
          }
        }

        if (rowIndex == 0 || rowIndex == this.rowsNum) {
          for (var colIndex = 0; colIndex < numCols; colIndex++) {
            cell = this.cloneCell(sourceCell, true);
            this.setCellContent(cell);
            cell.getAttribute("vAlign") && cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
            row.appendChild(cell);
            if (!isInsertTitle) replaceTdToTh(colIndex, cell, row)
          }
          if (isInsertTitle) {
            thead = table.createTHead();
            thead.insertBefore(row, thead.firstChild)
          }
        } else {
          var infoRow = this.indexTable[rowIndex], cellIndex = 0;
          for (colIndex = 0; colIndex < numCols; colIndex++) {
            var cellInfo = infoRow[colIndex];
            if (cellInfo.rowIndex < rowIndex) {
              cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
              cell.rowSpan = cellInfo.rowSpan + 1
            } else {
              cell = this.cloneCell(sourceCell, true);
              this.setCellContent(cell);
              row.appendChild(cell)
            }
            if (!isInsertTitle) replaceTdToTh(colIndex, cell, row)
          }
        }
        this.update();
        return row
      }, deleteRow: function (rowIndex) {
        var row = this.table.rows[rowIndex], infoRow = this.indexTable[rowIndex], colsNum = this.colsNum, count = 0;
        for (var colIndex = 0; colIndex < colsNum;) {
          var cellInfo = infoRow[colIndex], cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
          if (cell.rowSpan > 1) {
            if (cellInfo.rowIndex == rowIndex) {
              var clone = cell.cloneNode(true);
              clone.rowSpan = cell.rowSpan - 1;
              clone.innerHTML = "";
              cell.rowSpan = 1;
              var nextRowIndex = rowIndex + 1, nextRow = this.table.rows[nextRowIndex], insertCellIndex, preMerged = this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count;
              if (preMerged < colIndex) {
                insertCellIndex = colIndex - preMerged - 1;
                domUtils.insertAfter(nextRow.cells[insertCellIndex], clone)
              } else {
                if (nextRow.cells.length) nextRow.insertBefore(clone, nextRow.cells[0])
              }
              count += 1
            }
          }
          colIndex += cell.colSpan || 1
        }
        var deleteTds = [], cacheMap = {};
        for (colIndex = 0; colIndex < colsNum; colIndex++) {
          var tmpRowIndex = infoRow[colIndex].rowIndex, tmpCellIndex = infoRow[colIndex].cellIndex, key = tmpRowIndex + "_" + tmpCellIndex;
          if (cacheMap[key]) continue;
          cacheMap[key] = 1;
          cell = this.getCell(tmpRowIndex, tmpCellIndex);
          deleteTds.push(cell)
        }
        var mergeTds = [];
        utils.each(deleteTds, function (td) {
          if (td.rowSpan == 1) {
            td.parentNode.removeChild(td)
          } else {
            mergeTds.push(td)
          }
        });
        utils.each(mergeTds, function (td) {
          td.rowSpan--
        });
        row.parentNode.removeChild(row);
        this.update()
      }, insertCol: function (colIndex, sourceCell, defaultValue) {
        var rowsNum = this.rowsNum, rowIndex = 0, tableRow, cell, backWidth = parseInt((this.table.offsetWidth - (this.colsNum + 1) * 20 - (this.colsNum + 1)) / (this.colsNum + 1), 10),
          isInsertTitleCol = typeof sourceCell == "string" && sourceCell.toUpperCase() == "TH";

        function replaceTdToTh(rowIndex, cell, tableRow) {
          if (rowIndex == 0) {
            var th = cell.nextSibling || cell.previousSibling;
            if (th.tagName == "TH") {
              th = cell.ownerDocument.createElement("th");
              th.appendChild(cell.firstChild);
              tableRow.insertBefore(th, cell);
              domUtils.remove(cell)
            }
          } else {
            if (cell.tagName == "TH") {
              var td = cell.ownerDocument.createElement("td");
              td.appendChild(cell.firstChild);
              tableRow.insertBefore(td, cell);
              domUtils.remove(cell)
            }
          }
        }

        var preCell;
        if (colIndex == 0 || colIndex == this.colsNum) {
          for (; rowIndex < rowsNum; rowIndex++) {
            tableRow = this.table.rows[rowIndex];
            preCell = tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length];
            cell = this.cloneCell(sourceCell, true);
            this.setCellContent(cell);
            cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
            preCell && cell.setAttribute("width", preCell.getAttribute("width"));
            if (!colIndex) {
              tableRow.insertBefore(cell, tableRow.cells[0])
            } else {
              domUtils.insertAfter(tableRow.cells[tableRow.cells.length - 1], cell)
            }
            if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow)
          }
        } else {
          for (; rowIndex < rowsNum; rowIndex++) {
            var cellInfo = this.indexTable[rowIndex][colIndex];
            if (cellInfo.colIndex < colIndex) {
              cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
              cell.colSpan = cellInfo.colSpan + 1
            } else {
              tableRow = this.table.rows[rowIndex];
              preCell = tableRow.cells[cellInfo.cellIndex];
              cell = this.cloneCell(sourceCell, true);
              this.setCellContent(cell);
              cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
              preCell && cell.setAttribute("width", preCell.getAttribute("width"));
              preCell ? tableRow.insertBefore(cell, preCell) : tableRow.appendChild(cell)
            }
            if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow)
          }
        }
        this.update();
        this.updateWidth(backWidth, defaultValue || {tdPadding: 10, tdBorder: 1})
      }, updateWidth: function (width, defaultValue) {
        var table = this.table, tmpWidth = UETable.getWidth(table) - defaultValue.tdPadding * 2 - defaultValue.tdBorder + width;
        if (tmpWidth < table.ownerDocument.body.offsetWidth) {
          table.setAttribute("width", tmpWidth);
          return
        }
        var tds = domUtils.getElementsByTagName(this.table, "td th");
        utils.each(tds, function (td) {
          td.setAttribute("width", width)
        })
      }, deleteCol: function (colIndex) {
        var indexTable = this.indexTable, tableRows = this.table.rows, backTableWidth = this.table.getAttribute("width"), backTdWidth = 0, rowsNum = this.rowsNum, cacheMap = {};
        for (var rowIndex = 0; rowIndex < rowsNum;) {
          var infoRow = indexTable[rowIndex], cellInfo = infoRow[colIndex], key = cellInfo.rowIndex + "_" + cellInfo.colIndex;
          if (cacheMap[key]) continue;
          cacheMap[key] = 1;
          var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
          if (!backTdWidth) backTdWidth = cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0);
          if (cell.colSpan > 1) {
            cell.colSpan--
          } else {
            tableRows[rowIndex].deleteCell(cellInfo.cellIndex)
          }
          rowIndex += cellInfo.rowSpan || 1
        }
        this.table.setAttribute("width", backTableWidth - backTdWidth);
        this.update()
      }, splitToCells: function (cell) {
        var me = this, cells = this.splitToRows(cell);
        utils.each(cells, function (cell) {
          me.splitToCols(cell)
        })
      }, splitToRows: function (cell) {
        var cellInfo = this.getCellInfo(cell), rowIndex = cellInfo.rowIndex, colIndex = cellInfo.colIndex, results = [];
        cell.rowSpan = 1;
        results.push(cell);
        for (var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan; i < endRow; i++) {
          if (i == rowIndex) continue;
          var tableRow = this.table.rows[i], tmpCell = tableRow.insertCell(colIndex - this.getPreviewMergedCellsNum(i, colIndex));
          tmpCell.colSpan = cellInfo.colSpan;
          this.setCellContent(tmpCell);
          tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign"));
          tmpCell.setAttribute("align", cell.getAttribute("align"));
          if (cell.style.cssText) {
            tmpCell.style.cssText = cell.style.cssText
          }
          results.push(tmpCell)
        }
        this.update();
        return results
      }, getPreviewMergedCellsNum: function (rowIndex, colIndex) {
        var indexRow = this.indexTable[rowIndex], num = 0;
        for (var i = 0; i < colIndex;) {
          var colSpan = indexRow[i].colSpan, tmpRowIndex = indexRow[i].rowIndex;
          num += colSpan - (tmpRowIndex == rowIndex ? 1 : 0);
          i += colSpan
        }
        return num
      }, splitToCols: function (cell) {
        var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0), cellInfo = this.getCellInfo(cell), rowIndex = cellInfo.rowIndex, colIndex = cellInfo.colIndex, results = [];
        cell.colSpan = 1;
        cell.setAttribute("width", backWidth);
        results.push(cell);
        for (var j = colIndex, endCol = colIndex + cellInfo.colSpan; j < endCol; j++) {
          if (j == colIndex) continue;
          var tableRow = this.table.rows[rowIndex], tmpCell = tableRow.insertCell(this.indexTable[rowIndex][j].cellIndex + 1);
          tmpCell.rowSpan = cellInfo.rowSpan;
          this.setCellContent(tmpCell);
          tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign"));
          tmpCell.setAttribute("align", cell.getAttribute("align"));
          tmpCell.setAttribute("width", backWidth);
          if (cell.style.cssText) {
            tmpCell.style.cssText = cell.style.cssText
          }
          if (cell.tagName == "TH") {
            var th = cell.ownerDocument.createElement("th");
            th.appendChild(tmpCell.firstChild);
            th.setAttribute("vAlign", cell.getAttribute("vAlign"));
            th.rowSpan = tmpCell.rowSpan;
            tableRow.insertBefore(th, tmpCell);
            domUtils.remove(tmpCell)
          }
          results.push(tmpCell)
        }
        this.update();
        return results
      }, isLastCell: function (cell, rowsNum, colsNum) {
        rowsNum = rowsNum || this.rowsNum;
        colsNum = colsNum || this.colsNum;
        var cellInfo = this.getCellInfo(cell);
        return cellInfo.rowIndex + cellInfo.rowSpan == rowsNum && cellInfo.colIndex + cellInfo.colSpan == colsNum
      }, getLastCell: function (cells) {
        cells = cells || this.table.getElementsByTagName("td");
        var firstInfo = this.getCellInfo(cells[0]);
        var me = this, last = cells[0], tr = last.parentNode, cellsNum = 0, cols = 0, rows;
        utils.each(cells, function (cell) {
          if (cell.parentNode == tr) cols += cell.colSpan || 1;
          cellsNum += cell.rowSpan * cell.colSpan || 1
        });
        rows = cellsNum / cols;
        utils.each(cells, function (cell) {
          if (me.isLastCell(cell, rows, cols)) {
            last = cell;
            return false
          }
        });
        return last
      }, selectRow: function (rowIndex) {
        var indexRow = this.indexTable[rowIndex], start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex), end = this.getCell(indexRow[this.colsNum - 1].rowIndex, indexRow[this.colsNum - 1].cellIndex),
          range = this.getCellsRange(start, end);
        this.setSelected(range)
      }, selectTable: function () {
        var tds = this.table.getElementsByTagName("td"), range = this.getCellsRange(tds[0], tds[tds.length - 1]);
        this.setSelected(range)
      }, setBackground: function (cells, value) {
        if (typeof value === "string") {
          utils.each(cells, function (cell) {
            cell.style.backgroundColor = value
          })
        } else if (typeof value === "object") {
          value = utils.extend({repeat: true, colorList: ["#ddd", "#fff"]}, value);
          var rowIndex = this.getCellInfo(cells[0]).rowIndex, count = 0, colors = value.colorList, getColor = function (list, index, repeat) {
            return list[index] ? list[index] : repeat ? list[index % list.length] : ""
          };
          for (var i = 0, cell; cell = cells[i++];) {
            var cellInfo = this.getCellInfo(cell);
            cell.style.backgroundColor = getColor(colors, rowIndex + count == cellInfo.rowIndex ? count : ++count, value.repeat)
          }
        }
      }, removeBackground: function (cells) {
        utils.each(cells, function (cell) {
          cell.style.backgroundColor = ""
        })
      }
    };

    function showError(e) {
    }
  })();
  (function () {
    var UT = UE.UETable, getTableItemsByRange = function (editor) {
      return UT.getTableItemsByRange(editor)
    }, getUETableBySelected = function (editor) {
      return UT.getUETableBySelected(editor)
    }, getDefaultValue = function (editor, table) {
      return UT.getDefaultValue(editor, table)
    }, getUETable = function (tdOrTable) {
      return UT.getUETable(tdOrTable)
    };
    UE.commands["inserttable"] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? -1 : 0
      }, execCommand: function (cmd, opt) {
        function createTable(opt, tdWidth) {
          var html = [], rowsNum = opt.numRows, colsNum = opt.numCols;
          for (var r = 0; r < rowsNum; r++) {
            html.push("<tr" + (r == 0 ? ' class="firstRow"' : "") + ">");
            for (var c = 0; c < colsNum; c++) {
              html.push('<td width="' + tdWidth + '"  vAlign="' + opt.tdvalign + '" >' + (browser.ie && browser.version < 11 ? domUtils.fillChar : "<br/>") + "</td>")
            }
            html.push("</tr>")
          }
          return "<table><tbody>" + html.join("") + "</tbody></table>"
        }

        if (!opt) {
          opt = utils.extend({}, {numCols: this.options.defaultCols, numRows: this.options.defaultRows, tdvalign: this.options.tdvalign})
        }
        var me = this;
        var range = this.selection.getRange(), start = range.startContainer, firstParentBlock = domUtils.findParent(start, function (node) {
          return domUtils.isBlockElm(node)
        }, true) || me.body;
        var defaultValue = getDefaultValue(me), tableWidth = firstParentBlock.offsetWidth, tdWidth = Math.floor(tableWidth / opt.numCols - defaultValue.tdPadding * 2 - defaultValue.tdBorder);
        !opt.tdvalign && (opt.tdvalign = me.options.tdvalign);
        me.execCommand("inserthtml", createTable(opt, tdWidth))
      }
    };
    UE.commands["insertparagraphbeforetable"] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).cell ? 0 : -1
      }, execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var p = this.document.createElement("p");
          p.innerHTML = browser.ie ? "&nbsp;" : "<br />";
          table.parentNode.insertBefore(p, table);
          this.selection.getRange().setStart(p, 0).setCursor()
        }
      }
    };
    UE.commands["deletetable"] = {
      queryCommandState: function () {
        var rng = this.selection.getRange();
        return domUtils.findParentByTagName(rng.startContainer, "table", true) ? 0 : -1
      }, execCommand: function (cmd, table) {
        var rng = this.selection.getRange();
        table = table || domUtils.findParentByTagName(rng.startContainer, "table", true);
        if (table) {
          var next = table.nextSibling;
          if (!next) {
            next = domUtils.createElement(this.document, "p", {innerHTML: browser.ie ? domUtils.fillChar : "<br/>"});
            table.parentNode.insertBefore(next, table)
          }
          domUtils.remove(table);
          rng = this.selection.getRange();
          if (next.nodeType == 3) {
            rng.setStartBefore(next)
          } else {
            rng.setStart(next, 0)
          }
          rng.setCursor(false, true);
          this.fireEvent("tablehasdeleted")
        }
      }
    };
    UE.commands["cellalign"] = {
      queryCommandState: function () {
        return getSelectedArr(this).length ? 0 : -1
      }, execCommand: function (cmd, align) {
        var selectedTds = getSelectedArr(this);
        if (selectedTds.length) {
          for (var i = 0, ci; ci = selectedTds[i++];) {
            ci.setAttribute("align", align)
          }
        }
      }
    };
    UE.commands["cellvalign"] = {
      queryCommandState: function () {
        return getSelectedArr(this).length ? 0 : -1
      }, execCommand: function (cmd, valign) {
        var selectedTds = getSelectedArr(this);
        if (selectedTds.length) {
          for (var i = 0, ci; ci = selectedTds[i++];) {
            ci.setAttribute("vAlign", valign)
          }
        }
      }
    };
    UE.commands["insertcaption"] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          return table.getElementsByTagName("caption").length == 0 ? 1 : -1
        }
        return -1
      }, execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var caption = this.document.createElement("caption");
          caption.innerHTML = browser.ie ? domUtils.fillChar : "<br/>";
          table.insertBefore(caption, table.firstChild);
          var range = this.selection.getRange();
          range.setStart(caption, 0).setCursor()
        }
      }
    };
    UE.commands["deletecaption"] = {
      queryCommandState: function () {
        var rng = this.selection.getRange(), table = domUtils.findParentByTagName(rng.startContainer, "table");
        if (table) {
          return table.getElementsByTagName("caption").length == 0 ? -1 : 1
        }
        return -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), table = domUtils.findParentByTagName(rng.startContainer, "table");
        if (table) {
          domUtils.remove(table.getElementsByTagName("caption")[0]);
          var range = this.selection.getRange();
          range.setStart(table.rows[0].cells[0], 0).setCursor()
        }
      }
    };
    UE.commands["inserttitle"] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var firstRow = table.rows[0];
          return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() != "th" ? 0 : -1
        }
        return -1
      }, execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          getUETable(table).insertRow(0, "th")
        }
        var th = table.getElementsByTagName("th")[0];
        this.selection.getRange().setStart(th, 0).setCursor(false, true)
      }
    };
    UE.commands["deletetitle"] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var firstRow = table.rows[0];
          return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() == "th" ? 0 : -1
        }
        return -1
      }, execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          domUtils.remove(table.rows[0])
        }
        var td = table.getElementsByTagName("td")[0];
        this.selection.getRange().setStart(td, 0).setCursor(false, true)
      }
    };
    UE.commands["inserttitlecol"] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var lastRow = table.rows[table.rows.length - 1];
          return lastRow.getElementsByTagName("th").length ? -1 : 0
        }
        return -1
      }, execCommand: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (table) {
          getUETable(table).insertCol(0, "th")
        }
        resetTdWidth(table, this);
        var th = table.getElementsByTagName("th")[0];
        this.selection.getRange().setStart(th, 0).setCursor(false, true)
      }
    };
    UE.commands["deletetitlecol"] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var lastRow = table.rows[table.rows.length - 1];
          return lastRow.getElementsByTagName("th").length ? 0 : -1
        }
        return -1
      }, execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          for (var i = 0; i < table.rows.length; i++) {
            domUtils.remove(table.rows[i].children[0])
          }
        }
        resetTdWidth(table, this);
        var td = table.getElementsByTagName("td")[0];
        this.selection.getRange().setStart(td, 0).setCursor(false, true)
      }
    };
    UE.commands["mergeright"] = {
      queryCommandState: function (cmd) {
        var tableItems = getTableItemsByRange(this), table = tableItems.table, cell = tableItems.cell;
        if (!table || !cell) return -1;
        var ut = getUETable(table);
        if (ut.selectedTds.length) return -1;
        var cellInfo = ut.getCellInfo(cell), rightColIndex = cellInfo.colIndex + cellInfo.colSpan;
        if (rightColIndex >= ut.colsNum) return -1;
        var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex], rightCell = table.rows[rightCellInfo.rowIndex].cells[rightCellInfo.cellIndex];
        if (!rightCell || cell.tagName != rightCell.tagName) return -1;
        return rightCellInfo.rowIndex == cellInfo.rowIndex && rightCellInfo.rowSpan == cellInfo.rowSpan ? 0 : -1
      }, execCommand: function (cmd) {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell);
        ut.mergeRight(cell);
        rng.moveToBookmark(bk).select()
      }
    };
    UE.commands["mergedown"] = {
      queryCommandState: function (cmd) {
        var tableItems = getTableItemsByRange(this), table = tableItems.table, cell = tableItems.cell;
        if (!table || !cell) return -1;
        var ut = getUETable(table);
        if (ut.selectedTds.length) return -1;
        var cellInfo = ut.getCellInfo(cell), downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan;
        if (downRowIndex >= ut.rowsNum) return -1;
        var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex], downCell = table.rows[downCellInfo.rowIndex].cells[downCellInfo.cellIndex];
        if (!downCell || cell.tagName != downCell.tagName) return -1;
        return downCellInfo.colIndex == cellInfo.colIndex && downCellInfo.colSpan == cellInfo.colSpan ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell);
        ut.mergeDown(cell);
        rng.moveToBookmark(bk).select()
      }
    };
    UE.commands["mergecells"] = {
      queryCommandState: function () {
        return getUETableBySelected(this) ? 0 : -1
      }, execCommand: function () {
        var ut = getUETableBySelected(this);
        if (ut && ut.selectedTds.length) {
          var cell = ut.selectedTds[0];
          ut.mergeRange();
          var rng = this.selection.getRange();
          if (domUtils.isEmptyBlock(cell)) {
            rng.setStart(cell, 0).collapse(true)
          } else {
            rng.selectNodeContents(cell)
          }
          rng.select()
        }
      }
    };
    UE.commands["insertrow"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        return cell && (cell.tagName == "TD" || cell.tagName == "TH" && tableItems.tr !== tableItems.table.rows[0]) && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell, table = tableItems.table, ut = getUETable(table), cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertRow(cellInfo.rowIndex, cell)
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
            ut.insertRow(range.beginRowIndex, cell)
          }
        }
        rng.moveToBookmark(bk).select();
        if (table.getAttribute("interlaced") === "enabled") this.fireEvent("interlacetable", table)
      }
    };
    UE.commands["insertrownext"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        return cell && cell.tagName == "TD" && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell, table = tableItems.table, ut = getUETable(table), cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertRow(cellInfo.rowIndex + cellInfo.rowSpan, cell)
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
            ut.insertRow(range.endRowIndex + 1, cell)
          }
        }
        rng.moveToBookmark(bk).select();
        if (table.getAttribute("interlaced") === "enabled") this.fireEvent("interlacetable", table)
      }
    };
    UE.commands["deleterow"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this);
        return tableItems.cell ? 0 : -1
      }, execCommand: function () {
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), cellsRange = ut.cellsRange, cellInfo = ut.getCellInfo(cell), preCell = ut.getVSideCell(cell), nextCell = ut.getVSideCell(cell, true), rng = this.selection.getRange();
        if (utils.isEmptyObject(cellsRange)) {
          ut.deleteRow(cellInfo.rowIndex)
        } else {
          for (var i = cellsRange.beginRowIndex; i < cellsRange.endRowIndex + 1; i++) {
            ut.deleteRow(cellsRange.beginRowIndex)
          }
        }
        var table = ut.table;
        if (!table.getElementsByTagName("td").length) {
          var nextSibling = table.nextSibling;
          domUtils.remove(table);
          if (nextSibling) {
            rng.setStart(nextSibling, 0).setCursor(false, true)
          }
        } else {
          if (cellInfo.rowSpan == 1 || cellInfo.rowSpan == cellsRange.endRowIndex - cellsRange.beginRowIndex + 1) {
            if (nextCell || preCell) rng.selectNodeContents(nextCell || preCell).setCursor(false, true)
          } else {
            var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex);
            if (newCell) rng.selectNodeContents(newCell).setCursor(false, true)
          }
        }
        if (table.getAttribute("interlaced") === "enabled") this.fireEvent("interlacetable", table)
      }
    };
    UE.commands["insertcol"] = {
      queryCommandState: function (cmd) {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        return cell && (cell.tagName == "TD" || cell.tagName == "TH" && cell !== tableItems.tr.cells[0]) && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1
      }, execCommand: function (cmd) {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        if (this.queryCommandState(cmd) == -1) return;
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertCol(cellInfo.colIndex, cell)
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
            ut.insertCol(range.beginColIndex, cell)
          }
        }
        rng.moveToBookmark(bk).select(true)
      }
    };
    UE.commands["insertcolnext"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        return cell && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertCol(cellInfo.colIndex + cellInfo.colSpan, cell)
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
            ut.insertCol(range.endColIndex + 1, cell)
          }
        }
        rng.moveToBookmark(bk).select()
      }
    };
    UE.commands["deletecol"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this);
        return tableItems.cell ? 0 : -1
      }, execCommand: function () {
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell), range = ut.cellsRange, cellInfo = ut.getCellInfo(cell), preCell = ut.getHSideCell(cell), nextCell = ut.getHSideCell(cell, true);
        if (utils.isEmptyObject(range)) {
          ut.deleteCol(cellInfo.colIndex)
        } else {
          for (var i = range.beginColIndex; i < range.endColIndex + 1; i++) {
            ut.deleteCol(range.beginColIndex)
          }
        }
        var table = ut.table, rng = this.selection.getRange();
        if (!table.getElementsByTagName("td").length) {
          var nextSibling = table.nextSibling;
          domUtils.remove(table);
          if (nextSibling) {
            rng.setStart(nextSibling, 0).setCursor(false, true)
          }
        } else {
          if (domUtils.inDoc(cell, this.document)) {
            rng.setStart(cell, 0).setCursor(false, true)
          } else {
            if (nextCell && domUtils.inDoc(nextCell, this.document)) {
              rng.selectNodeContents(nextCell).setCursor(false, true)
            } else {
              if (preCell && domUtils.inDoc(preCell, this.document)) {
                rng.selectNodeContents(preCell).setCursor(true, true)
              }
            }
          }
        }
      }
    };
    UE.commands["splittocells"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        if (!cell) return -1;
        var ut = getUETable(tableItems.table);
        if (ut.selectedTds.length > 0) return -1;
        return cell && (cell.colSpan > 1 || cell.rowSpan > 1) ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell);
        ut.splitToCells(cell);
        rng.moveToBookmark(bk).select()
      }
    };
    UE.commands["splittorows"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        if (!cell) return -1;
        var ut = getUETable(tableItems.table);
        if (ut.selectedTds.length > 0) return -1;
        return cell && cell.rowSpan > 1 ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell);
        ut.splitToRows(cell);
        rng.moveToBookmark(bk).select()
      }
    };
    UE.commands["splittocols"] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this), cell = tableItems.cell;
        if (!cell) return -1;
        var ut = getUETable(tableItems.table);
        if (ut.selectedTds.length > 0) return -1;
        return cell && cell.colSpan > 1 ? 0 : -1
      }, execCommand: function () {
        var rng = this.selection.getRange(), bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell, ut = getUETable(cell);
        ut.splitToCols(cell);
        rng.moveToBookmark(bk).select()
      }
    };
    UE.commands["adaptbytext"] = UE.commands["adaptbywindow"] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1
      }, execCommand: function (cmd) {
        var tableItems = getTableItemsByRange(this), table = tableItems.table;
        if (table) {
          if (cmd == "adaptbywindow") {
            resetTdWidth(table, this)
          } else {
            var cells = domUtils.getElementsByTagName(table, "td th");
            utils.each(cells, function (cell) {
              cell.removeAttribute("width")
            });
            table.removeAttribute("width")
          }
        }
      }
    };
    UE.commands["averagedistributecol"] = {
      queryCommandState: function () {
        var ut = getUETableBySelected(this);
        if (!ut) return -1;
        return ut.isFullRow() || ut.isFullCol() ? 0 : -1
      }, execCommand: function (cmd) {
        var me = this, ut = getUETableBySelected(me);

        function getAverageWidth() {
          var tb = ut.table, averageWidth, sumWidth = 0, colsNum = 0, tbAttr = getDefaultValue(me, tb);
          if (ut.isFullRow()) {
            sumWidth = tb.offsetWidth;
            colsNum = ut.colsNum
          } else {
            var begin = ut.cellsRange.beginColIndex, end = ut.cellsRange.endColIndex, node;
            for (var i = begin; i <= end;) {
              node = ut.selectedTds[i];
              sumWidth += node.offsetWidth;
              i += node.colSpan;
              colsNum += 1
            }
          }
          averageWidth = Math.ceil(sumWidth / colsNum) - tbAttr.tdBorder * 2 - tbAttr.tdPadding * 2;
          return averageWidth
        }

        function setAverageWidth(averageWidth) {
          utils.each(domUtils.getElementsByTagName(ut.table, "th"), function (node) {
            node.setAttribute("width", "")
          });
          var cells = ut.isFullRow() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds;
          utils.each(cells, function (node) {
            if (node.colSpan == 1) {
              node.setAttribute("width", averageWidth)
            }
          })
        }

        if (ut && ut.selectedTds.length) {
          setAverageWidth(getAverageWidth())
        }
      }
    };
    UE.commands["averagedistributerow"] = {
      queryCommandState: function () {
        var ut = getUETableBySelected(this);
        if (!ut) return -1;
        if (ut.selectedTds && /th/gi.test(ut.selectedTds[0].tagName)) return -1;
        return ut.isFullRow() || ut.isFullCol() ? 0 : -1
      }, execCommand: function (cmd) {
        var me = this, ut = getUETableBySelected(me);

        function getAverageHeight() {
          var averageHeight, rowNum, sumHeight = 0, tb = ut.table, tbAttr = getDefaultValue(me, tb), tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName("td")[0], "padding-top"));
          if (ut.isFullCol()) {
            var captionArr = domUtils.getElementsByTagName(tb, "caption"), thArr = domUtils.getElementsByTagName(tb, "th"), captionHeight, thHeight;
            if (captionArr.length > 0) {
              captionHeight = captionArr[0].offsetHeight
            }
            if (thArr.length > 0) {
              thHeight = thArr[0].offsetHeight
            }
            sumHeight = tb.offsetHeight - (captionHeight || 0) - (thHeight || 0);
            rowNum = thArr.length == 0 ? ut.rowsNum : ut.rowsNum - 1
          } else {
            var begin = ut.cellsRange.beginRowIndex, end = ut.cellsRange.endRowIndex, count = 0, trs = domUtils.getElementsByTagName(tb, "tr");
            for (var i = begin; i <= end; i++) {
              sumHeight += trs[i].offsetHeight;
              count += 1
            }
            rowNum = count
          }
          if (browser.ie && browser.version < 9) {
            averageHeight = Math.ceil(sumHeight / rowNum)
          } else {
            averageHeight = Math.ceil(sumHeight / rowNum) - tbAttr.tdBorder * 2 - tdpadding * 2
          }
          return averageHeight
        }

        function setAverageHeight(averageHeight) {
          var cells = ut.isFullCol() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds;
          utils.each(cells, function (node) {
            if (node.rowSpan == 1) {
              node.setAttribute("height", averageHeight)
            }
          })
        }

        if (ut && ut.selectedTds.length) {
          setAverageHeight(getAverageHeight())
        }
      }
    };
    UE.commands["cellalignment"] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1
      }, execCommand: function (cmd, data) {
        var me = this, ut = getUETableBySelected(me);
        if (!ut) {
          var start = me.selection.getStart(), cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
          if (!/caption/gi.test(cell.tagName)) {
            domUtils.setAttributes(cell, data)
          } else {
            cell.style.textAlign = data.align;
            cell.style.verticalAlign = data.vAlign
          }
          me.selection.getRange().setCursor(true)
        } else {
          utils.each(ut.selectedTds, function (cell) {
            domUtils.setAttributes(cell, data)
          })
        }
      }, queryCommandValue: function (cmd) {
        var activeMenuCell = getTableItemsByRange(this).cell;
        if (!activeMenuCell) {
          activeMenuCell = getSelectedArr(this)[0]
        }
        if (!activeMenuCell) {
          return null
        } else {
          var cells = UE.UETable.getUETable(activeMenuCell).selectedTds;
          !cells.length && (cells = activeMenuCell);
          return UE.UETable.getTableCellAlignState(cells)
        }
      }
    };
    UE.commands["tablealignment"] = {
      queryCommandState: function () {
        if (browser.ie && browser.version < 8) {
          return -1
        }
        return getTableItemsByRange(this).table ? 0 : -1
      }, execCommand: function (cmd, value) {
        var me = this, start = me.selection.getStart(), table = start && domUtils.findParentByTagName(start, ["table"], true);
        if (table) {
          table.setAttribute("align", value)
        }
      }
    };
    UE.commands["edittable"] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1
      }, execCommand: function (cmd, color) {
        var rng = this.selection.getRange(), table = domUtils.findParentByTagName(rng.startContainer, "table");
        if (table) {
          var arr = domUtils.getElementsByTagName(table, "td").concat(domUtils.getElementsByTagName(table, "th"), domUtils.getElementsByTagName(table, "caption"));
          utils.each(arr, function (node) {
            node.style.borderColor = color
          })
        }
      }
    };
    UE.commands["edittd"] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1
      }, execCommand: function (cmd, bkColor) {
        var me = this, ut = getUETableBySelected(me);
        if (!ut) {
          var start = me.selection.getStart(), cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
          if (cell) {
            cell.style.backgroundColor = bkColor
          }
        } else {
          utils.each(ut.selectedTds, function (cell) {
            cell.style.backgroundColor = bkColor
          })
        }
      }
    };
    UE.commands["settablebackground"] = {
      queryCommandState: function () {
        return getSelectedArr(this).length > 1 ? 0 : -1
      }, execCommand: function (cmd, value) {
        var cells, ut;
        cells = getSelectedArr(this);
        ut = getUETable(cells[0]);
        ut.setBackground(cells, value)
      }
    };
    UE.commands["cleartablebackground"] = {
      queryCommandState: function () {
        var cells = getSelectedArr(this);
        if (!cells.length) return -1;
        for (var i = 0, cell; cell = cells[i++];) {
          if (cell.style.backgroundColor !== "") return 0
        }
        return -1
      }, execCommand: function () {
        var cells = getSelectedArr(this), ut = getUETable(cells[0]);
        ut.removeBackground(cells)
      }
    };
    UE.commands["interlacetable"] = UE.commands["uninterlacetable"] = {
      queryCommandState: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (!table) return -1;
        var interlaced = table.getAttribute("interlaced");
        if (cmd == "interlacetable") {
          return interlaced === "enabled" ? -1 : 0
        } else {
          return !interlaced || interlaced === "disabled" ? -1 : 0
        }
      }, execCommand: function (cmd, classList) {
        var table = getTableItemsByRange(this).table;
        if (cmd == "interlacetable") {
          table.setAttribute("interlaced", "enabled");
          this.fireEvent("interlacetable", table, classList)
        } else {
          table.setAttribute("interlaced", "disabled");
          this.fireEvent("uninterlacetable", table)
        }
      }
    };
    UE.commands["setbordervisible"] = {
      queryCommandState: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (!table) return -1;
        return 0
      }, execCommand: function () {
        var table = getTableItemsByRange(this).table;
        utils.each(domUtils.getElementsByTagName(table, "td"), function (td) {
          td.style.borderWidth = "1px";
          td.style.borderStyle = "solid"
        })
      }
    };

    function resetTdWidth(table, editor) {
      var tds = domUtils.getElementsByTagName(table, "td th");
      utils.each(tds, function (td) {
        td.removeAttribute("width")
      });
      table.setAttribute("width", getTableWidth(editor, true, getDefaultValue(editor, table)));
      var tdsWidths = [];
      setTimeout(function () {
        utils.each(tds, function (td) {
          td.colSpan == 1 && tdsWidths.push(td.offsetWidth)
        });
        utils.each(tds, function (td, i) {
          td.colSpan == 1 && td.setAttribute("width", tdsWidths[i] + "")
        })
      }, 0)
    }

    function getTableWidth(editor, needIEHack, defaultValue) {
      var body = editor.body;
      return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0)
    }

    function getSelectedArr(editor) {
      var cell = getTableItemsByRange(editor).cell;
      if (cell) {
        var ut = getUETable(cell);
        return ut.selectedTds.length ? ut.selectedTds : [cell]
      } else {
        return []
      }
    }
  })();
  UE.plugins["table"] = function () {
    var me = this, tabTimer = null, tableDragTimer = null, tableResizeTimer = null, cellMinWidth = 5, isInResizeBuffer = false, cellBorderWidth = 5, offsetOfTableCell = 10, singleClickState = 0, userActionStatus = null, dblclickTime = 200,
      UT = UE.UETable, getUETable = function (tdOrTable) {
        return UT.getUETable(tdOrTable)
      }, getUETableBySelected = function (editor) {
        return UT.getUETableBySelected(editor)
      }, getDefaultValue = function (editor, table) {
        return UT.getDefaultValue(editor, table)
      }, removeSelectedClass = function (cells) {
        return UT.removeSelectedClass(cells)
      };

    function showError(e) {
    }

    me.ready(function () {
      var me = this;
      var orgGetText = me.selection.getText;
      me.selection.getText = function () {
        var table = getUETableBySelected(me);
        if (table) {
          var str = "";
          utils.each(table.selectedTds, function (td) {
            str += td[browser.ie ? "innerText" : "textContent"]
          });
          return str
        } else {
          return orgGetText.call(me.selection)
        }
      }
    });
    var startTd = null, currentTd = null, onDrag = "", onBorder = false, dragButton = null, dragOver = false, dragLine = null, dragTd = null;
    var mousedown = false, needIEHack = true;
    me.setOpt({
      maxColNum: 20,
      maxRowNum: 100,
      defaultCols: 5,
      defaultRows: 5,
      tdvalign: "top",
      cursorpath: me.options.UEDITOR_HOME_URL + "themes/default/images/cursor_",
      tableDragable: false,
      classList: ["ue-table-interlace-color-single", "ue-table-interlace-color-double"]
    });
    me.getUETable = getUETable;
    var commands = {
      deletetable: 1,
      inserttable: 1,
      cellvalign: 1,
      insertcaption: 1,
      deletecaption: 1,
      inserttitle: 1,
      deletetitle: 1,
      mergeright: 1,
      mergedown: 1,
      mergecells: 1,
      insertrow: 1,
      insertrownext: 1,
      deleterow: 1,
      insertcol: 1,
      insertcolnext: 1,
      deletecol: 1,
      splittocells: 1,
      splittorows: 1,
      splittocols: 1,
      adaptbytext: 1,
      adaptbywindow: 1,
      adaptbycustomer: 1,
      insertparagraph: 1,
      insertparagraphbeforetable: 1,
      averagedistributecol: 1,
      averagedistributerow: 1
    };
    me.ready(function () {
      utils.cssRule("table", ".selectTdClass{background-color:#edf5fa !important}" + "table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}" + "table{margin-bottom:10px;border-collapse:collapse;display:table;}" + "td,th{padding: 5px 10px;border: 1px solid #DDD;}" + "caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}" + "th{border-top:1px solid #BBB;background-color:#F7F7F7;}" + "table tr.firstRow th{border-top-width:2px;}" + ".ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }" + "td p{margin:0;padding:0;}", me.document);
      var tableCopyList, isFullCol, isFullRow;
      me.addListener("keydown", function (cmd, evt) {
        var me = this;
        var keyCode = evt.keyCode || evt.which;
        if (keyCode == 8) {
          var ut = getUETableBySelected(me);
          if (ut && ut.selectedTds.length) {
            if (ut.isFullCol()) {
              me.execCommand("deletecol")
            } else if (ut.isFullRow()) {
              me.execCommand("deleterow")
            } else {
              me.fireEvent("delcells")
            }
            domUtils.preventDefault(evt)
          }
          var caption = domUtils.findParentByTagName(me.selection.getStart(), "caption", true), range = me.selection.getRange();
          if (range.collapsed && caption && isEmptyBlock(caption)) {
            me.fireEvent("saveScene");
            var table = caption.parentNode;
            domUtils.remove(caption);
            if (table) {
              range.setStart(table.rows[0].cells[0], 0).setCursor(false, true)
            }
            me.fireEvent("saveScene")
          }
        }
        if (keyCode == 46) {
          ut = getUETableBySelected(me);
          if (ut) {
            me.fireEvent("saveScene");
            for (var i = 0, ci; ci = ut.selectedTds[i++];) {
              domUtils.fillNode(me.document, ci)
            }
            me.fireEvent("saveScene");
            domUtils.preventDefault(evt)
          }
        }
        if (keyCode == 13) {
          var rng = me.selection.getRange(), caption = domUtils.findParentByTagName(rng.startContainer, "caption", true);
          if (caption) {
            var table = domUtils.findParentByTagName(caption, "table");
            if (!rng.collapsed) {
              rng.deleteContents();
              me.fireEvent("saveScene")
            } else {
              if (caption) {
                rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true)
              }
            }
            domUtils.preventDefault(evt);
            return
          }
          if (rng.collapsed) {
            var table = domUtils.findParentByTagName(rng.startContainer, "table");
            if (table) {
              var cell = table.rows[0].cells[0], start = domUtils.findParentByTagName(me.selection.getStart(), ["td", "th"], true), preNode = table.previousSibling;
              if (cell === start && (!preNode || preNode.nodeType == 1 && preNode.tagName == "TABLE") && domUtils.isStartInblock(rng)) {
                var first = domUtils.findParent(me.selection.getStart(), function (n) {
                  return domUtils.isBlockElm(n)
                }, true);
                if (first && (/t(h|d)/i.test(first.tagName) || first === start.firstChild)) {
                  me.execCommand("insertparagraphbeforetable");
                  domUtils.preventDefault(evt)
                }
              }
            }
          }
        }
        if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == "67") {
          tableCopyList = null;
          var ut = getUETableBySelected(me);
          if (ut) {
            var tds = ut.selectedTds;
            isFullCol = ut.isFullCol();
            isFullRow = ut.isFullRow();
            tableCopyList = [[ut.cloneCell(tds[0], null, true)]];
            for (var i = 1, ci; ci = tds[i]; i++) {
              if (ci.parentNode !== tds[i - 1].parentNode) {
                tableCopyList.push([ut.cloneCell(ci, null, true)])
              } else {
                tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci, null, true))
              }
            }
          }
        }
      });
      me.addListener("tablehasdeleted", function () {
        toggleDraggableState(this, false, "", null);
        if (dragButton) domUtils.remove(dragButton)
      });
      me.addListener("beforepaste", function (cmd, html) {
        var me = this;
        var rng = me.selection.getRange();
        if (domUtils.findParentByTagName(rng.startContainer, "caption", true)) {
          var div = me.document.createElement("div");
          div.innerHTML = html.html;
          html.html = div[browser.ie9below ? "innerText" : "textContent"];
          return
        }
        var table = getUETableBySelected(me);
        if (tableCopyList) {
          me.fireEvent("saveScene");
          var rng = me.selection.getRange();
          var td = domUtils.findParentByTagName(rng.startContainer, ["td", "th"], true), tmpNode, preNode;
          if (td) {
            var ut = getUETable(td);
            if (isFullRow) {
              var rowIndex = ut.getCellInfo(td).rowIndex;
              if (td.tagName == "TH") {
                rowIndex++
              }
              for (var i = 0, ci; ci = tableCopyList[i++];) {
                var tr = ut.insertRow(rowIndex++, "td");
                for (var j = 0, cj; cj = ci[j]; j++) {
                  var cell = tr.cells[j];
                  if (!cell) {
                    cell = tr.insertCell(j)
                  }
                  cell.innerHTML = cj.innerHTML;
                  cj.getAttribute("width") && cell.setAttribute("width", cj.getAttribute("width"));
                  cj.getAttribute("vAlign") && cell.setAttribute("vAlign", cj.getAttribute("vAlign"));
                  cj.getAttribute("align") && cell.setAttribute("align", cj.getAttribute("align"));
                  cj.style.cssText && (cell.style.cssText = cj.style.cssText)
                }
                for (var j = 0, cj; cj = tr.cells[j]; j++) {
                  if (!ci[j]) break;
                  cj.innerHTML = ci[j].innerHTML;
                  ci[j].getAttribute("width") && cj.setAttribute("width", ci[j].getAttribute("width"));
                  ci[j].getAttribute("vAlign") && cj.setAttribute("vAlign", ci[j].getAttribute("vAlign"));
                  ci[j].getAttribute("align") && cj.setAttribute("align", ci[j].getAttribute("align"));
                  ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText)
                }
              }
            } else {
              if (isFullCol) {
                cellInfo = ut.getCellInfo(td);
                var maxColNum = 0;
                for (var j = 0, ci = tableCopyList[0], cj; cj = ci[j++];) {
                  maxColNum += cj.colSpan || 1
                }
                me.__hasEnterExecCommand = true;
                for (i = 0; i < maxColNum; i++) {
                  me.execCommand("insertcol")
                }
                me.__hasEnterExecCommand = false;
                td = ut.table.rows[0].cells[cellInfo.cellIndex];
                if (td.tagName == "TH") {
                  td = ut.table.rows[1].cells[cellInfo.cellIndex]
                }
              }
              for (var i = 0, ci; ci = tableCopyList[i++];) {
                tmpNode = td;
                for (var j = 0, cj; cj = ci[j++];) {
                  if (td) {
                    td.innerHTML = cj.innerHTML;
                    cj.getAttribute("width") && td.setAttribute("width", cj.getAttribute("width"));
                    cj.getAttribute("vAlign") && td.setAttribute("vAlign", cj.getAttribute("vAlign"));
                    cj.getAttribute("align") && td.setAttribute("align", cj.getAttribute("align"));
                    cj.style.cssText && (td.style.cssText = cj.style.cssText);
                    preNode = td;
                    td = td.nextSibling
                  } else {
                    var cloneTd = cj.cloneNode(true);
                    domUtils.removeAttributes(cloneTd, ["class", "rowSpan", "colSpan"]);
                    preNode.parentNode.appendChild(cloneTd)
                  }
                }
                td = ut.getNextCell(tmpNode, true, true);
                if (!tableCopyList[i]) break;
                if (!td) {
                  var cellInfo = ut.getCellInfo(tmpNode);
                  ut.table.insertRow(ut.table.rows.length);
                  ut.update();
                  td = ut.getVSideCell(tmpNode, true)
                }
              }
            }
            ut.update()
          } else {
            table = me.document.createElement("table");
            for (var i = 0, ci; ci = tableCopyList[i++];) {
              var tr = table.insertRow(table.rows.length);
              for (var j = 0, cj; cj = ci[j++];) {
                cloneTd = UT.cloneCell(cj, null, true);
                domUtils.removeAttributes(cloneTd, ["class"]);
                tr.appendChild(cloneTd)
              }
              if (j == 2 && cloneTd.rowSpan > 1) {
                cloneTd.rowSpan = 1
              }
            }
            var defaultValue = getDefaultValue(me), width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0);
            me.execCommand("insertHTML", "<table  " + (isFullCol && isFullRow ? 'width="' + width + '"' : "") + ">" + table.innerHTML.replace(/>\s*</g, "><").replace(/\bth\b/gi, "td") + "</table>")
          }
          me.fireEvent("contentchange");
          me.fireEvent("saveScene");
          html.html = "";
          return true
        } else {
          var div = me.document.createElement("div"), tables;
          div.innerHTML = html.html;
          tables = div.getElementsByTagName("table");
          if (domUtils.findParentByTagName(me.selection.getStart(), "table")) {
            utils.each(tables, function (t) {
              domUtils.remove(t)
            });
            if (domUtils.findParentByTagName(me.selection.getStart(), "caption", true)) {
              div.innerHTML = div[browser.ie ? "innerText" : "textContent"]
            }
          } else {
            utils.each(tables, function (table) {
              removeStyleSize(table, true);
              domUtils.removeAttributes(table, ["style", "border"]);
              utils.each(domUtils.getElementsByTagName(table, "td"), function (td) {
                if (isEmptyBlock(td)) {
                  domUtils.fillNode(me.document, td)
                }
                removeStyleSize(td, true)
              })
            })
          }
          html.html = div.innerHTML
        }
      });
      me.addListener("afterpaste", function () {
        utils.each(domUtils.getElementsByTagName(me.body, "table"), function (table) {
          if (table.offsetWidth > me.body.offsetWidth) {
            var defaultValue = getDefaultValue(me, table);
            table.style.width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0) + "px"
          }
        })
      });
      me.addListener("blur", function () {
        tableCopyList = null
      });
      var timer;
      me.addListener("keydown", function () {
        clearTimeout(timer);
        timer = setTimeout(function () {
          var rng = me.selection.getRange(), cell = domUtils.findParentByTagName(rng.startContainer, ["th", "td"], true);
          if (cell) {
            var table = cell.parentNode.parentNode.parentNode;
            if (table.offsetWidth > table.getAttribute("width")) {
              cell.style.wordBreak = "break-all"
            }
          }
        }, 100)
      });
      me.addListener("selectionchange", function () {
        toggleDraggableState(me, false, "", null)
      });
      me.addListener("contentchange", function () {
        var me = this;
        hideDragLine(me);
        if (getUETableBySelected(me)) return;
        var rng = me.selection.getRange();
        var start = rng.startContainer;
        start = domUtils.findParentByTagName(start, ["td", "th"], true);
        utils.each(domUtils.getElementsByTagName(me.document, "table"), function (table) {
          if (me.fireEvent("excludetable", table) === true) return;
          table.ueTable = new UT(table);
          table.onmouseover = function () {
            me.fireEvent("tablemouseover", table)
          };
          table.onmousemove = function () {
            me.fireEvent("tablemousemove", table);
            me.options.tableDragable && toggleDragButton(true, this, me);
            utils.defer(function () {
              me.fireEvent("contentchange", 50)
            }, true)
          };
          table.onmouseout = function () {
            me.fireEvent("tablemouseout", table);
            toggleDraggableState(me, false, "", null);
            hideDragLine(me)
          };
          table.onclick = function (evt) {
            evt = me.window.event || evt;
            var target = getParentTdOrTh(evt.target || evt.srcElement);
            if (!target) return;
            var ut = getUETable(target), table = ut.table, cellInfo = ut.getCellInfo(target), cellsRange, rng = me.selection.getRange();
            if (inTableSide(table, target, evt, true)) {
              var endTdCol = ut.getCell(ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex, ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex);
              if (evt.shiftKey && ut.selectedTds.length) {
                if (ut.selectedTds[0] !== endTdCol) {
                  cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);
                  ut.setSelected(cellsRange)
                } else {
                  rng && rng.selectNodeContents(endTdCol).select()
                }
              } else {
                if (target !== endTdCol) {
                  cellsRange = ut.getCellsRange(target, endTdCol);
                  ut.setSelected(cellsRange)
                } else {
                  rng && rng.selectNodeContents(endTdCol).select()
                }
              }
              return
            }
            if (inTableSide(table, target, evt)) {
              var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex, ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex);
              if (evt.shiftKey && ut.selectedTds.length) {
                if (ut.selectedTds[0] !== endTdRow) {
                  cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);
                  ut.setSelected(cellsRange)
                } else {
                  rng && rng.selectNodeContents(endTdRow).select()
                }
              } else {
                if (target !== endTdRow) {
                  cellsRange = ut.getCellsRange(target, endTdRow);
                  ut.setSelected(cellsRange)
                } else {
                  rng && rng.selectNodeContents(endTdRow).select()
                }
              }
            }
          }
        });
        switchBorderColor(me, true)
      });
      domUtils.on(me.document, "mousemove", mouseMoveEvent);
      domUtils.on(me.document, "mouseout", function (evt) {
        var target = evt.target || evt.srcElement;
        if (target.tagName == "TABLE") {
          toggleDraggableState(me, false, "", null)
        }
      });
      me.addListener("interlacetable", function (type, table, classList) {
        if (!table) return;
        var me = this, rows = table.rows, len = rows.length, getClass = function (list, index, repeat) {
          return list[index] ? list[index] : repeat ? list[index % list.length] : ""
        };
        for (var i = 0; i < len; i++) {
          rows[i].className = getClass(classList || me.options.classList, i, true)
        }
      });
      me.addListener("uninterlacetable", function (type, table) {
        if (!table) return;
        var me = this, rows = table.rows, classList = me.options.classList, len = rows.length;
        for (var i = 0; i < len; i++) {
          domUtils.removeClasses(rows[i], classList)
        }
      });
      me.addListener("mousedown", mouseDownEvent);
      me.addListener("mouseup", mouseUpEvent);
      domUtils.on(me.body, "dragstart", function (evt) {
        mouseUpEvent.call(me, "dragstart", evt)
      });
      me.addOutputRule(function (root) {
        utils.each(root.getNodesByTagName("div"), function (n) {
          if (n.getAttr("id") == "ue_tableDragLine") {
            n.parentNode.removeChild(n)
          }
        })
      });
      var currentRowIndex = 0;
      me.addListener("mousedown", function () {
        currentRowIndex = 0
      });
      me.addListener("tabkeydown", function () {
        var range = this.selection.getRange(), common = range.getCommonAncestor(true, true), table = domUtils.findParentByTagName(common, "table");
        if (table) {
          if (domUtils.findParentByTagName(common, "caption", true)) {
            var cell = domUtils.getElementsByTagName(table, "th td");
            if (cell && cell.length) {
              range.setStart(cell[0], 0).setCursor(false, true)
            }
          } else {
            var cell = domUtils.findParentByTagName(common, ["td", "th"], true), ua = getUETable(cell);
            currentRowIndex = cell.rowSpan > 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex;
            var nextCell = ua.getTabNextCell(cell, currentRowIndex);
            if (nextCell) {
              if (isEmptyBlock(nextCell)) {
                range.setStart(nextCell, 0).setCursor(false, true)
              } else {
                range.selectNodeContents(nextCell).select()
              }
            } else {
              me.fireEvent("saveScene");
              me.__hasEnterExecCommand = true;
              this.execCommand("insertrownext");
              me.__hasEnterExecCommand = false;
              range = this.selection.getRange();
              range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor();
              me.fireEvent("saveScene")
            }
          }
          return true
        }
      });
      browser.ie && me.addListener("selectionchange", function () {
        toggleDraggableState(this, false, "", null)
      });
      me.addListener("keydown", function (type, evt) {
        var me = this;
        var keyCode = evt.keyCode || evt.which;
        if (keyCode == 8 || keyCode == 46) {
          return
        }
        var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;
        notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, "td"));
        var ut = getUETableBySelected(me);
        if (!ut) return;
        notCtrlKey && ut.clearSelected()
      });
      me.addListener("beforegetcontent", function () {
        switchBorderColor(this, false);
        browser.ie && utils.each(this.document.getElementsByTagName("caption"), function (ci) {
          if (domUtils.isEmptyNode(ci)) {
            ci.innerHTML = "&nbsp;"
          }
        })
      });
      me.addListener("aftergetcontent", function () {
        switchBorderColor(this, true)
      });
      me.addListener("getAllHtml", function () {
        removeSelectedClass(me.document.getElementsByTagName("td"))
      });
      me.addListener("fullscreenchanged", function (type, fullscreen) {
        if (!fullscreen) {
          var ratio = this.body.offsetWidth / document.body.offsetWidth, tables = domUtils.getElementsByTagName(this.body, "table");
          utils.each(tables, function (table) {
            if (table.offsetWidth < me.body.offsetWidth) return false;
            var tds = domUtils.getElementsByTagName(table, "td"), backWidths = [];
            utils.each(tds, function (td) {
              backWidths.push(td.offsetWidth)
            });
            for (var i = 0, td; td = tds[i]; i++) {
              td.setAttribute("width", Math.floor(backWidths[i] * ratio))
            }
            table.setAttribute("width", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me))))
          })
        }
      });
      var oldExecCommand = me.execCommand;
      me.execCommand = function (cmd, datatat) {
        var me = this, args = arguments;
        cmd = cmd.toLowerCase();
        var ut = getUETableBySelected(me), tds, range = new dom.Range(me.document), cmdFun = me.commands[cmd] || UE.commands[cmd], result;
        if (!cmdFun) return;
        if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) {
          me.__hasEnterExecCommand = true;
          me.fireEvent("beforeexeccommand", cmd);
          tds = ut.selectedTds;
          var lastState = -2, lastValue = -2, value, state;
          for (var i = 0, td; td = tds[i]; i++) {
            if (isEmptyBlock(td)) {
              range.setStart(td, 0).setCursor(false, true)
            } else {
              range.selectNode(td).select(true)
            }
            state = me.queryCommandState(cmd);
            value = me.queryCommandValue(cmd);
            if (state != -1) {
              if (lastState !== state || lastValue !== value) {
                me._ignoreContentChange = true;
                result = oldExecCommand.apply(me, arguments);
                me._ignoreContentChange = false
              }
              lastState = me.queryCommandState(cmd);
              lastValue = me.queryCommandValue(cmd);
              if (domUtils.isEmptyBlock(td)) {
                domUtils.fillNode(me.document, td)
              }
            }
          }
          range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);
          me.fireEvent("contentchange");
          me.fireEvent("afterexeccommand", cmd);
          me.__hasEnterExecCommand = false;
          me._selectionChange()
        } else {
          result = oldExecCommand.apply(me, arguments)
        }
        return result
      }
    });

    function removeStyleSize(obj, replaceToProperty) {
      removeStyle(obj, "width", true);
      removeStyle(obj, "height", true)
    }

    function removeStyle(obj, styleName, replaceToProperty) {
      if (obj.style[styleName]) {
        replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));
        obj.style[styleName] = ""
      }
    }

    function getParentTdOrTh(ele) {
      if (ele.tagName == "TD" || ele.tagName == "TH") return ele;
      var td;
      if (td = domUtils.findParentByTagName(ele, "td", true) || domUtils.findParentByTagName(ele, "th", true)) return td;
      return null
    }

    function isEmptyBlock(node) {
      var reg = new RegExp(domUtils.fillChar, "g");
      if (node[browser.ie ? "innerText" : "textContent"].replace(/^\s*$/, "").replace(reg, "").length > 0) {
        return 0
      }
      for (var n in dtd.$isNotEmpty) {
        if (node.getElementsByTagName(n).length) {
          return 0
        }
      }
      return 1
    }

    function mouseCoords(evt) {
      if (evt.pageX || evt.pageY) {
        return {x: evt.pageX, y: evt.pageY}
      }
      return {x: evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft, y: evt.clientY + me.document.body.scrollTop - me.document.body.clientTop}
    }

    function mouseMoveEvent(evt) {
      if (isEditorDisabled()) {
        return
      }
      try {
        var target = getParentTdOrTh(evt.target || evt.srcElement), pos;
        if (isInResizeBuffer) {
          me.body.style.webkitUserSelect = "none";
          if (Math.abs(userActionStatus.x - evt.clientX) > offsetOfTableCell || Math.abs(userActionStatus.y - evt.clientY) > offsetOfTableCell) {
            clearTableDragTimer();
            isInResizeBuffer = false;
            singleClickState = 0;
            tableBorderDrag(evt)
          }
        }
        if (onDrag && dragTd) {
          singleClickState = 0;
          me.body.style.webkitUserSelect = "none";
          me.selection.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]();
          pos = mouseCoords(evt);
          toggleDraggableState(me, true, onDrag, pos, target);
          if (onDrag == "h") {
            dragLine.style.left = getPermissionX(dragTd, evt) + "px"
          } else if (onDrag == "v") {
            dragLine.style.top = getPermissionY(dragTd, evt) + "px"
          }
          return
        }
        if (target) {
          if (me.fireEvent("excludetable", target) === true) return;
          pos = mouseCoords(evt);
          var state = getRelation(target, pos), table = domUtils.findParentByTagName(target, "table", true);
          if (inTableSide(table, target, evt, true)) {
            if (me.fireEvent("excludetable", table) === true) return;
            me.body.style.cursor = "url(" + me.options.cursorpath + "h.png),pointer"
          } else if (inTableSide(table, target, evt)) {
            if (me.fireEvent("excludetable", table) === true) return;
            me.body.style.cursor = "url(" + me.options.cursorpath + "v.png),pointer"
          } else {
            me.body.style.cursor = "text";
            var curCell = target;
            if (/\d/.test(state)) {
              state = state.replace(/\d/, "");
              target = getUETable(target).getPreviewCell(target, state == "v")
            }
            toggleDraggableState(me, target ? !!state : false, target ? state : "", pos, target)
          }
        } else {
          toggleDragButton(false, table, me)
        }
      } catch (e) {
        showError(e)
      }
    }

    var dragButtonTimer;

    function toggleDragButton(show, table, editor) {
      if (!show) {
        if (dragOver) return;
        dragButtonTimer = setTimeout(function () {
          !dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton)
        }, 2e3)
      } else {
        createDragButton(table, editor)
      }
    }

    function createDragButton(table, editor) {
      var pos = domUtils.getXY(table), doc = table.ownerDocument;
      if (dragButton && dragButton.parentNode) return dragButton;
      dragButton = doc.createElement("div");
      dragButton.contentEditable = false;
      dragButton.innerHTML = "";
      dragButton.style.cssText = "width:15px;height:15px;background-image:url(" + editor.options.UEDITOR_HOME_URL + "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" + (pos.y - 15) + "px;left:" + pos.x + "px;";
      domUtils.unSelectable(dragButton);
      dragButton.onmouseover = function (evt) {
        dragOver = true
      };
      dragButton.onmouseout = function (evt) {
        dragOver = false
      };
      domUtils.on(dragButton, "click", function (type, evt) {
        doClick(evt, this)
      });
      domUtils.on(dragButton, "dblclick", function (type, evt) {
        doDblClick(evt)
      });
      domUtils.on(dragButton, "dragstart", function (type, evt) {
        domUtils.preventDefault(evt)
      });
      var timer;

      function doClick(evt, button) {
        clearTimeout(timer);
        timer = setTimeout(function () {
          editor.fireEvent("tableClicked", table, button)
        }, 300)
      }

      function doDblClick(evt) {
        clearTimeout(timer);
        var ut = getUETable(table), start = table.rows[0].cells[0], end = ut.getLastCell(), range = ut.getCellsRange(start, end);
        editor.selection.getRange().setStart(start, 0).setCursor(false, true);
        ut.setSelected(range)
      }

      doc.body.appendChild(dragButton)
    }

    function inTableSide(table, cell, evt, top) {
      var pos = mouseCoords(evt), state = getRelation(cell, pos);
      if (top) {
        var caption = table.getElementsByTagName("caption")[0], capHeight = caption ? caption.offsetHeight : 0;
        return state == "v1" && pos.y - domUtils.getXY(table).y - capHeight < 8
      } else {
        return state == "h1" && pos.x - domUtils.getXY(table).x < 8
      }
    }

    function getPermissionX(dragTd, evt) {
      var ut = getUETable(dragTd);
      if (ut) {
        var preTd = ut.getSameEndPosCells(dragTd, "x")[0], nextTd = ut.getSameStartPosXCells(dragTd)[0], mouseX = mouseCoords(evt).x, left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20,
          right = nextTd ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20 : me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, "width"), 10);
        left += cellMinWidth;
        right -= cellMinWidth;
        return mouseX < left ? left : mouseX > right ? right : mouseX
      }
    }

    function getPermissionY(dragTd, evt) {
      try {
        var top = domUtils.getXY(dragTd).y, mousePosY = mouseCoords(evt).y;
        return mousePosY < top ? top : mousePosY
      } catch (e) {
        showError(e)
      }
    }

    function toggleDraggableState(editor, draggable, dir, mousePos, cell) {
      try {
        editor.body.style.cursor = dir == "h" ? "col-resize" : dir == "v" ? "row-resize" : "text";
        if (browser.ie) {
          if (dir && !mousedown && !getUETableBySelected(editor)) {
            getDragLine(editor, editor.document);
            showDragLineAt(dir, cell)
          } else {
            hideDragLine(editor)
          }
        }
        onBorder = draggable
      } catch (e) {
        showError(e)
      }
    }

    function getResizeLineByUETable() {
      var lineId = "_UETableResizeLine", line = this.document.getElementById(lineId);
      if (!line) {
        line = this.document.createElement("div");
        line.id = lineId;
        line.contnetEditable = false;
        line.setAttribute("unselectable", "on");
        var styles = {width: 2 * cellBorderWidth + 1 + "px", position: "absolute", "z-index": 1e5, cursor: "col-resize", background: "red", display: "none"};
        line.onmouseout = function () {
          this.style.display = "none"
        };
        utils.extend(line.style, styles);
        this.document.body.appendChild(line)
      }
      return line
    }

    function updateResizeLine(cell, uetable) {
      var line = getResizeLineByUETable.call(this), table = uetable.table, styles = {top: domUtils.getXY(table).y + "px", left: domUtils.getXY(cell).x + cell.offsetWidth - cellBorderWidth + "px", display: "block", height: table.offsetHeight + "px"};
      utils.extend(line.style, styles)
    }

    function showResizeLine(cell) {
      var uetable = getUETable(cell);
      updateResizeLine.call(this, cell, uetable)
    }

    function getRelation(ele, mousePos) {
      var elePos = domUtils.getXY(ele);
      if (!elePos) {
        return ""
      }
      if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {
        return "h"
      }
      if (mousePos.x - elePos.x < cellBorderWidth) {
        return "h1"
      }
      if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {
        return "v"
      }
      if (mousePos.y - elePos.y < cellBorderWidth) {
        return "v1"
      }
      return ""
    }

    function mouseDownEvent(type, evt) {
      if (isEditorDisabled()) {
        return
      }
      userActionStatus = {x: evt.clientX, y: evt.clientY};
      if (evt.button == 2) {
        var ut = getUETableBySelected(me), flag = false;
        if (ut) {
          var td = getTargetTd(me, evt);
          utils.each(ut.selectedTds, function (ti) {
            if (ti === td) {
              flag = true
            }
          });
          if (!flag) {
            removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td"));
            ut.clearSelected()
          } else {
            td = ut.selectedTds[0];
            setTimeout(function () {
              me.selection.getRange().setStart(td, 0).setCursor(false, true)
            }, 0)
          }
        }
      } else {
        tableClickHander(evt)
      }
    }

    function clearTableTimer() {
      tabTimer && clearTimeout(tabTimer);
      tabTimer = null
    }

    function tableDbclickHandler(evt) {
      singleClickState = 0;
      evt = evt || me.window.event;
      var target = getParentTdOrTh(evt.target || evt.srcElement);
      if (target) {
        var h;
        if (h = getRelation(target, mouseCoords(evt))) {
          hideDragLine(me);
          if (h == "h1") {
            h = "h";
            if (inTableSide(domUtils.findParentByTagName(target, "table"), target, evt)) {
              me.execCommand("adaptbywindow")
            } else {
              target = getUETable(target).getPreviewCell(target);
              if (target) {
                var rng = me.selection.getRange();
                rng.selectNodeContents(target).setCursor(true, true)
              }
            }
          }
          if (h == "h") {
            var ut = getUETable(target), table = ut.table, cells = getCellsByMoveBorder(target, table, true);
            cells = extractArray(cells, "left");
            ut.width = ut.offsetWidth;
            var oldWidth = [], newWidth = [];
            utils.each(cells, function (cell) {
              oldWidth.push(cell.offsetWidth)
            });
            utils.each(cells, function (cell) {
              cell.removeAttribute("width")
            });
            window.setTimeout(function () {
              var changeable = true;
              utils.each(cells, function (cell, index) {
                var width = cell.offsetWidth;
                if (width > oldWidth[index]) {
                  changeable = false;
                  return false
                }
                newWidth.push(width)
              });
              var change = changeable ? newWidth : oldWidth;
              utils.each(cells, function (cell, index) {
                cell.width = change[index] - getTabcellSpace()
              })
            }, 0)
          }
        }
      }
    }

    function tableClickHander(evt) {
      removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th"));
      utils.each(me.document.getElementsByTagName("table"), function (t) {
        t.ueTable = null
      });
      startTd = getTargetTd(me, evt);
      if (!startTd) return;
      var table = domUtils.findParentByTagName(startTd, "table", true);
      ut = getUETable(table);
      ut && ut.clearSelected();
      if (!onBorder) {
        me.document.body.style.webkitUserSelect = "";
        mousedown = true;
        me.addListener("mouseover", mouseOverEvent)
      } else {
        borderActionHandler(evt)
      }
    }

    function borderActionHandler(evt) {
      if (browser.ie) {
        evt = reconstruct(evt)
      }
      clearTableDragTimer();
      isInResizeBuffer = true;
      tableDragTimer = setTimeout(function () {
        tableBorderDrag(evt)
      }, dblclickTime)
    }

    function extractArray(originArr, key) {
      var result = [], tmp = null;
      for (var i = 0, len = originArr.length; i < len; i++) {
        tmp = originArr[i][key];
        if (tmp) {
          result.push(tmp)
        }
      }
      return result
    }

    function clearTableDragTimer() {
      tableDragTimer && clearTimeout(tableDragTimer);
      tableDragTimer = null
    }

    function reconstruct(obj) {
      var attrs = ["pageX", "pageY", "clientX", "clientY", "srcElement", "target"], newObj = {};
      if (obj) {
        for (var i = 0, key, val; key = attrs[i]; i++) {
          val = obj[key];
          val && (newObj[key] = val)
        }
      }
      return newObj
    }

    function tableBorderDrag(evt) {
      isInResizeBuffer = false;
      startTd = evt.target || evt.srcElement;
      if (!startTd) return;
      var state = getRelation(startTd, mouseCoords(evt));
      if (/\d/.test(state)) {
        state = state.replace(/\d/, "");
        startTd = getUETable(startTd).getPreviewCell(startTd, state == "v")
      }
      hideDragLine(me);
      getDragLine(me, me.document);
      me.fireEvent("saveScene");
      showDragLineAt(state, startTd);
      mousedown = true;
      onDrag = state;
      dragTd = startTd
    }

    function mouseUpEvent(type, evt) {
      if (isEditorDisabled()) {
        return
      }
      clearTableDragTimer();
      isInResizeBuffer = false;
      if (onBorder) {
        singleClickState = ++singleClickState % 3;
        userActionStatus = {x: evt.clientX, y: evt.clientY};
        tableResizeTimer = setTimeout(function () {
          singleClickState > 0 && singleClickState--
        }, dblclickTime);
        if (singleClickState === 2) {
          singleClickState = 0;
          tableDbclickHandler(evt);
          return
        }
      }
      if (evt.button == 2) return;
      var me = this;
      var range = me.selection.getRange(), start = domUtils.findParentByTagName(range.startContainer, "table", true), end = domUtils.findParentByTagName(range.endContainer, "table", true);
      if (start || end) {
        if (start === end) {
          start = domUtils.findParentByTagName(range.startContainer, ["td", "th", "caption"], true);
          end = domUtils.findParentByTagName(range.endContainer, ["td", "th", "caption"], true);
          if (start !== end) {
            me.selection.clearRange()
          }
        } else {
          me.selection.clearRange()
        }
      }
      mousedown = false;
      me.document.body.style.webkitUserSelect = "";
      if (onDrag && dragTd) {
        me.selection.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]();
        singleClickState = 0;
        dragLine = me.document.getElementById("ue_tableDragLine");
        if (dragLine) {
          var dragTdPos = domUtils.getXY(dragTd), dragLinePos = domUtils.getXY(dragLine);
          switch (onDrag) {
            case"h":
              changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);
              break;
            case"v":
              changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight);
              break;
            default:
          }
          onDrag = "";
          dragTd = null;
          hideDragLine(me);
          me.fireEvent("saveScene");
          return
        }
      }
      if (!startTd) {
        var target = domUtils.findParentByTagName(evt.target || evt.srcElement, "td", true);
        if (!target) target = domUtils.findParentByTagName(evt.target || evt.srcElement, "th", true);
        if (target && (target.tagName == "TD" || target.tagName == "TH")) {
          if (me.fireEvent("excludetable", target) === true) return;
          range = new dom.Range(me.document);
          range.setStart(target, 0).setCursor(false, true)
        }
      } else {
        var ut = getUETable(startTd), cell = ut ? ut.selectedTds[0] : null;
        if (cell) {
          range = new dom.Range(me.document);
          if (domUtils.isEmptyBlock(cell)) {
            range.setStart(cell, 0).setCursor(false, true)
          } else {
            range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true)
          }
        } else {
          range = me.selection.getRange().shrinkBoundary();
          if (!range.collapsed) {
            var start = domUtils.findParentByTagName(range.startContainer, ["td", "th"], true), end = domUtils.findParentByTagName(range.endContainer, ["td", "th"], true);
            if (start && !end || !start && end || start && end && start !== end) {
              range.setCursor(false, true)
            }
          }
        }
        startTd = null;
        me.removeListener("mouseover", mouseOverEvent)
      }
      me._selectionChange(250, evt)
    }

    function mouseOverEvent(type, evt) {
      if (isEditorDisabled()) {
        return
      }
      var me = this, tar = evt.target || evt.srcElement;
      currentTd = domUtils.findParentByTagName(tar, "td", true) || domUtils.findParentByTagName(tar, "th", true);
      if (startTd && currentTd && (startTd.tagName == "TD" && currentTd.tagName == "TD" || startTd.tagName == "TH" && currentTd.tagName == "TH") && domUtils.findParentByTagName(startTd, "table") == domUtils.findParentByTagName(currentTd, "table")) {
        var ut = getUETable(currentTd);
        if (startTd != currentTd) {
          me.document.body.style.webkitUserSelect = "none";
          me.selection.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]();
          var range = ut.getCellsRange(startTd, currentTd);
          ut.setSelected(range)
        } else {
          me.document.body.style.webkitUserSelect = "";
          ut.clearSelected()
        }
      }
      evt.preventDefault ? evt.preventDefault() : evt.returnValue = false
    }

    function setCellHeight(cell, height, backHeight) {
      var lineHight = parseInt(domUtils.getComputedStyle(cell, "line-height"), 10), tmpHeight = backHeight + height;
      height = tmpHeight < lineHight ? lineHight : tmpHeight;
      if (cell.style.height) cell.style.height = "";
      cell.rowSpan == 1 ? cell.setAttribute("height", height) : cell.removeAttribute && cell.removeAttribute("height")
    }

    function getWidth(cell) {
      if (!cell) return 0;
      return parseInt(domUtils.getComputedStyle(cell, "width"), 10)
    }

    function changeColWidth(cell, changeValue) {
      var ut = getUETable(cell);
      if (ut) {
        var table = ut.table, cells = getCellsByMoveBorder(cell, table);
        table.style.width = "";
        table.removeAttribute("width");
        changeValue = correctChangeValue(changeValue, cell, cells);
        if (cell.nextSibling) {
          var i = 0;
          utils.each(cells, function (cellGroup) {
            cellGroup.left.width = +cellGroup.left.width + changeValue;
            cellGroup.right && (cellGroup.right.width = +cellGroup.right.width - changeValue)
          })
        } else {
          utils.each(cells, function (cellGroup) {
            cellGroup.left.width -= -changeValue
          })
        }
      }
    }

    function isEditorDisabled() {
      return me.body.contentEditable === "false"
    }

    function changeRowHeight(td, changeValue) {
      if (Math.abs(changeValue) < 10) return;
      var ut = getUETable(td);
      if (ut) {
        var cells = ut.getSameEndPosCells(td, "y"), backHeight = cells[0] ? cells[0].offsetHeight : 0;
        for (var i = 0, cell; cell = cells[i++];) {
          setCellHeight(cell, changeValue, backHeight)
        }
      }
    }

    function getCellsByMoveBorder(cell, table, isContainMergeCell) {
      if (!table) {
        table = domUtils.findParentByTagName(cell, "table")
      }
      if (!table) {
        return null
      }
      var index = domUtils.getNodeIndex(cell), temp = cell, rows = table.rows, colIndex = 0;
      while (temp) {
        if (temp.nodeType === 1) {
          colIndex += temp.colSpan || 1
        }
        temp = temp.previousSibling
      }
      temp = null;
      var borderCells = [];
      utils.each(rows, function (tabRow) {
        var cells = tabRow.cells, currIndex = 0;
        utils.each(cells, function (tabCell) {
          currIndex += tabCell.colSpan || 1;
          if (currIndex === colIndex) {
            borderCells.push({left: tabCell, right: tabCell.nextSibling || null});
            return false
          } else if (currIndex > colIndex) {
            if (isContainMergeCell) {
              borderCells.push({left: tabCell})
            }
            return false
          }
        })
      });
      return borderCells
    }

    function getMinWidthByTableCells(cells) {
      var minWidth = Number.MAX_VALUE;
      for (var i = 0, curCell; curCell = cells[i]; i++) {
        minWidth = Math.min(minWidth, curCell.width || getTableCellWidth(curCell))
      }
      return minWidth
    }

    function correctChangeValue(changeValue, relatedCell, cells) {
      changeValue -= getTabcellSpace();
      if (changeValue < 0) {
        return 0
      }
      changeValue -= getTableCellWidth(relatedCell);
      var direction = changeValue < 0 ? "left" : "right";
      changeValue = Math.abs(changeValue);
      utils.each(cells, function (cellGroup) {
        var curCell = cellGroup[direction];
        if (curCell) {
          changeValue = Math.min(changeValue, getTableCellWidth(curCell) - cellMinWidth)
        }
      });
      changeValue = changeValue < 0 ? 0 : changeValue;
      return direction === "left" ? -changeValue : changeValue
    }

    function getTableCellWidth(cell) {
      var width = 0, offset = 0, width = cell.offsetWidth - getTabcellSpace();
      if (!cell.nextSibling) {
        width -= getTableCellOffset(cell)
      }
      width = width < 0 ? 0 : width;
      try {
        cell.width = width
      } catch (e) {
      }
      return width
    }

    function getTableCellOffset(cell) {
      tab = domUtils.findParentByTagName(cell, "table", false);
      if (tab.offsetVal === undefined) {
        var prev = cell.previousSibling;
        if (prev) {
          tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0
        } else {
          tab.offsetVal = 0
        }
      }
      return tab.offsetVal
    }

    function getTabcellSpace() {
      if (UT.tabcellSpace === undefined) {
        var cell = null, tab = me.document.createElement("table"), tbody = me.document.createElement("tbody"), trow = me.document.createElement("tr"), tabcell = me.document.createElement("td"), mirror = null;
        tabcell.style.cssText = "border: 0;";
        tabcell.width = 1;
        trow.appendChild(tabcell);
        trow.appendChild(mirror = tabcell.cloneNode(false));
        tbody.appendChild(trow);
        tab.appendChild(tbody);
        tab.style.cssText = "visibility: hidden;";
        me.body.appendChild(tab);
        UT.paddingSpace = tabcell.offsetWidth - 1;
        var tmpTabWidth = tab.offsetWidth;
        tabcell.style.cssText = "";
        mirror.style.cssText = "";
        UT.borderWidth = (tab.offsetWidth - tmpTabWidth) / 3;
        UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;
        me.body.removeChild(tab)
      }
      getTabcellSpace = function () {
        return UT.tabcellSpace
      };
      return UT.tabcellSpace
    }

    function getDragLine(editor, doc) {
      if (mousedown) return;
      dragLine = editor.document.createElement("div");
      domUtils.setAttributes(dragLine, {
        id: "ue_tableDragLine",
        unselectable: "on",
        contenteditable: false,
        onresizestart: "return false",
        ondragstart: "return false",
        onselectstart: "return false",
        style: "background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)"
      });
      editor.body.appendChild(dragLine)
    }

    function hideDragLine(editor) {
      if (mousedown) return;
      var line;
      while (line = editor.document.getElementById("ue_tableDragLine")) {
        domUtils.remove(line)
      }
    }

    function showDragLineAt(state, cell) {
      if (!cell) return;
      var table = domUtils.findParentByTagName(cell, "table"), caption = table.getElementsByTagName("caption"), width = table.offsetWidth, height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),
        tablePos = domUtils.getXY(table), cellPos = domUtils.getXY(cell), css;
      switch (state) {
        case"h":
          css = "height:" + height + "px;top:" + (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) + "px;left:" + (cellPos.x + cell.offsetWidth);
          dragLine.style.cssText = css + "px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)";
          break;
        case"v":
          css = "width:" + width + "px;left:" + tablePos.x + "px;top:" + (cellPos.y + cell.offsetHeight);
          dragLine.style.cssText = css + "px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)";
          break;
        default:
      }
    }

    function switchBorderColor(editor, flag) {
      var tableArr = domUtils.getElementsByTagName(editor.body, "table"), color;
      for (var i = 0, node; node = tableArr[i++];) {
        var td = domUtils.getElementsByTagName(node, "td");
        if (td[0]) {
          if (flag) {
            color = td[0].style.borderColor.replace(/\s/g, "");
            if (/(#ffffff)|(rgb\(255,255,255\))/gi.test(color)) domUtils.addClass(node, "noBorderTable")
          } else {
            domUtils.removeClasses(node, "noBorderTable")
          }
        }
      }
    }

    function getTableWidth(editor, needIEHack, defaultValue) {
      var body = editor.body;
      return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0)
    }

    function getTargetTd(editor, evt) {
      var target = domUtils.findParentByTagName(evt.target || evt.srcElement, ["td", "th"], true), dir = null;
      if (!target) {
        return null
      }
      dir = getRelation(target, mouseCoords(evt));
      if (!target) {
        return null
      }
      if (dir === "h1" && target.previousSibling) {
        var position = domUtils.getXY(target), cellWidth = target.offsetWidth;
        if (Math.abs(position.x + cellWidth - evt.clientX) > cellWidth / 3) {
          target = target.previousSibling
        }
      } else if (dir === "v1" && target.parentNode.previousSibling) {
        var position = domUtils.getXY(target), cellHeight = target.offsetHeight;
        if (Math.abs(position.y + cellHeight - evt.clientY) > cellHeight / 3) {
          target = target.parentNode.previousSibling.firstChild
        }
      }
      return target && !(editor.fireEvent("excludetable", target) === true) ? target : null
    }
  };
  UE.UETable.prototype.sortTable = function (sortByCellIndex, compareFn) {
    var table = this.table, rows = table.rows, trArray = [], flag = rows[0].cells[0].tagName === "TH", lastRowIndex = 0;
    if (this.selectedTds.length) {
      var range = this.cellsRange, len = range.endRowIndex + 1;
      for (var i = range.beginRowIndex; i < len; i++) {
        trArray[i] = rows[i]
      }
      trArray.splice(0, range.beginRowIndex);
      lastRowIndex = range.endRowIndex + 1 === this.rowsNum ? 0 : range.endRowIndex + 1
    } else {
      for (var i = 0, len = rows.length; i < len; i++) {
        trArray[i] = rows[i]
      }
    }
    var Fn = {
      reversecurrent: function (td1, td2) {
        return 1
      }, orderbyasc: function (td1, td2) {
        var value1 = td1.innerText || td1.textContent, value2 = td2.innerText || td2.textContent;
        return value1.localeCompare(value2)
      }, reversebyasc: function (td1, td2) {
        var value1 = td1.innerHTML, value2 = td2.innerHTML;
        return value2.localeCompare(value1)
      }, orderbynum: function (td1, td2) {
        var value1 = td1[browser.ie ? "innerText" : "textContent"].match(/\d+/), value2 = td2[browser.ie ? "innerText" : "textContent"].match(/\d+/);
        if (value1) value1 = +value1[0];
        if (value2) value2 = +value2[0];
        return (value1 || 0) - (value2 || 0)
      }, reversebynum: function (td1, td2) {
        var value1 = td1[browser.ie ? "innerText" : "textContent"].match(/\d+/), value2 = td2[browser.ie ? "innerText" : "textContent"].match(/\d+/);
        if (value1) value1 = +value1[0];
        if (value2) value2 = +value2[0];
        return (value2 || 0) - (value1 || 0)
      }
    };
    table.setAttribute("data-sort-type", compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn : "");
    flag && trArray.splice(0, 1);
    trArray = utils.sort(trArray, function (tr1, tr2) {
      var result;
      if (compareFn && typeof compareFn === "function") {
        result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])
      } else if (compareFn && typeof compareFn === "number") {
        result = 1
      } else if (compareFn && typeof compareFn === "string" && Fn[compareFn]) {
        result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])
      } else {
        result = Fn["orderbyasc"].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])
      }
      return result
    });
    var fragment = table.ownerDocument.createDocumentFragment();
    for (var j = 0, len = trArray.length; j < len; j++) {
      fragment.appendChild(trArray[j])
    }
    var tbody = table.getElementsByTagName("tbody")[0];
    if (!lastRowIndex) {
      tbody.appendChild(fragment)
    } else {
      tbody.insertBefore(fragment, rows[lastRowIndex - range.endRowIndex + range.beginRowIndex - 1])
    }
  };
  UE.plugins["tablesort"] = function () {
    var me = this, UT = UE.UETable, getUETable = function (tdOrTable) {
      return UT.getUETable(tdOrTable)
    }, getTableItemsByRange = function (editor) {
      return UT.getTableItemsByRange(editor)
    };
    me.ready(function () {
      utils.cssRule("tablesort", "table.sortEnabled tr.firstRow th,table.sortEnabled tr.firstRow td{padding-right:20px;background-repeat: no-repeat;background-position: center right;" + "   background-image:url(" + me.options.themePath + me.options.theme + "/images/sortable.png);}", me.document);
      me.addListener("afterexeccommand", function (type, cmd) {
        if (cmd == "mergeright" || cmd == "mergedown" || cmd == "mergecells") {
          this.execCommand("disablesort")
        }
      })
    });
    UE.commands["sorttable"] = {
      queryCommandState: function () {
        var me = this, tableItems = getTableItemsByRange(me);
        if (!tableItems.cell) return -1;
        var table = tableItems.table, cells = table.getElementsByTagName("td");
        for (var i = 0, cell; cell = cells[i++];) {
          if (cell.rowSpan != 1 || cell.colSpan != 1) return -1
        }
        return 0
      }, execCommand: function (cmd, fn) {
        var me = this, range = me.selection.getRange(), bk = range.createBookmark(true), tableItems = getTableItemsByRange(me), cell = tableItems.cell, ut = getUETable(tableItems.table), cellInfo = ut.getCellInfo(cell);
        ut.sortTable(cellInfo.cellIndex, fn);
        range.moveToBookmark(bk);
        try {
          range.select()
        } catch (e) {
        }
      }
    };
    UE.commands["enablesort"] = UE.commands["disablesort"] = {
      queryCommandState: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (table && cmd == "enablesort") {
          var cells = domUtils.getElementsByTagName(table, "th td");
          for (var i = 0; i < cells.length; i++) {
            if (cells[i].getAttribute("colspan") > 1 || cells[i].getAttribute("rowspan") > 1) return -1
          }
        }
        return !table ? -1 : cmd == "enablesort" ^ table.getAttribute("data-sort") != "sortEnabled" ? -1 : 0
      }, execCommand: function (cmd) {
        var table = getTableItemsByRange(this).table;
        table.setAttribute("data-sort", cmd == "enablesort" ? "sortEnabled" : "sortDisabled");
        cmd == "enablesort" ? domUtils.addClass(table, "sortEnabled") : domUtils.removeClasses(table, "sortEnabled")
      }
    }
  };
  UE.plugins["contextmenu"] = function () {
    var me = this;
    me.setOpt("enableContextMenu", me.getOpt("enableContextMenu") || true);
    if (me.getOpt("enableContextMenu") === false) {
      return
    }
    var lang = me.getLang("contextMenu"), menu, items = me.options.contextMenu || [{label: lang["selectall"], cmdName: "selectall"}, {
      label: lang.cleardoc, cmdName: "cleardoc", exec: function () {
        if (confirm(lang.confirmclear)) {
          this.execCommand("cleardoc")
        }
      }
    }, "-", {label: lang.unlink, cmdName: "unlink"}, "-", {
      group: lang.paragraph,
      icon: "justifyjustify",
      subMenu: [{label: lang.justifyleft, cmdName: "justify", value: "left"}, {label: lang.justifyright, cmdName: "justify", value: "right"}, {label: lang.justifycenter, cmdName: "justify", value: "center"}, {
        label: lang.justifyjustify,
        cmdName: "justify",
        value: "justify"
      }]
    }, "-", {
      group: lang.table,
      icon: "table",
      subMenu: [{label: lang.inserttable, cmdName: "inserttable"}, {label: lang.deletetable, cmdName: "deletetable"}, "-", {label: lang.deleterow, cmdName: "deleterow"}, {label: lang.deletecol, cmdName: "deletecol"}, {
        label: lang.insertcol,
        cmdName: "insertcol"
      }, {label: lang.insertcolnext, cmdName: "insertcolnext"}, {label: lang.insertrow, cmdName: "insertrow"}, {label: lang.insertrownext, cmdName: "insertrownext"}, "-", {
        label: lang.insertcaption,
        cmdName: "insertcaption"
      }, {label: lang.deletecaption, cmdName: "deletecaption"}, {label: lang.inserttitle, cmdName: "inserttitle"}, {label: lang.deletetitle, cmdName: "deletetitle"}, {
        label: lang.inserttitlecol,
        cmdName: "inserttitlecol"
      }, {label: lang.deletetitlecol, cmdName: "deletetitlecol"}, "-", {label: lang.mergecells, cmdName: "mergecells"}, {label: lang.mergeright, cmdName: "mergeright"}, {label: lang.mergedown, cmdName: "mergedown"}, "-", {
        label: lang.splittorows,
        cmdName: "splittorows"
      }, {label: lang.splittocols, cmdName: "splittocols"}, {label: lang.splittocells, cmdName: "splittocells"}, "-", {label: lang.averageDiseRow, cmdName: "averagedistributerow"}, {
        label: lang.averageDisCol,
        cmdName: "averagedistributecol"
      }, "-", {
        label: lang.edittd, cmdName: "edittd", exec: function () {
          if (UE.ui["edittd"]) {
            new UE.ui["edittd"](this)
          }
          this.getDialog("edittd").open()
        }
      }, {
        label: lang.edittable, cmdName: "edittable", exec: function () {
          if (UE.ui["edittable"]) {
            new UE.ui["edittable"](this)
          }
          this.getDialog("edittable").open()
        }
      }, {label: lang.setbordervisible, cmdName: "setbordervisible"}]
    }, {
      group: lang.tablesort,
      icon: "tablesort",
      subMenu: [{label: lang.enablesort, cmdName: "enablesort"}, {label: lang.disablesort, cmdName: "disablesort"}, "-", {label: lang.reversecurrent, cmdName: "sorttable", value: "reversecurrent"}, {
        label: lang.orderbyasc,
        cmdName: "sorttable",
        value: "orderbyasc"
      }, {label: lang.reversebyasc, cmdName: "sorttable", value: "reversebyasc"}, {label: lang.orderbynum, cmdName: "sorttable", value: "orderbynum"}, {label: lang.reversebynum, cmdName: "sorttable", value: "reversebynum"}]
    }, {
      group: lang.borderbk, icon: "borderBack", subMenu: [{
        label: lang.setcolor, cmdName: "interlacetable", exec: function () {
          this.execCommand("interlacetable")
        }
      }, {
        label: lang.unsetcolor, cmdName: "uninterlacetable", exec: function () {
          this.execCommand("uninterlacetable")
        }
      }, {
        label: lang.setbackground, cmdName: "settablebackground", exec: function () {
          this.execCommand("settablebackground", {repeat: true, colorList: ["#bbb", "#ccc"]})
        }
      }, {
        label: lang.unsetbackground, cmdName: "cleartablebackground", exec: function () {
          this.execCommand("cleartablebackground")
        }
      }, {
        label: lang.redandblue, cmdName: "settablebackground", exec: function () {
          this.execCommand("settablebackground", {repeat: true, colorList: ["red", "blue"]})
        }
      }, {
        label: lang.threecolorgradient, cmdName: "settablebackground", exec: function () {
          this.execCommand("settablebackground", {repeat: true, colorList: ["#aaa", "#bbb", "#ccc"]})
        }
      }]
    }, {
      group: lang.aligntd,
      icon: "aligntd",
      subMenu: [{cmdName: "cellalignment", value: {align: "left", vAlign: "top"}}, {cmdName: "cellalignment", value: {align: "center", vAlign: "top"}}, {cmdName: "cellalignment", value: {align: "right", vAlign: "top"}}, {
        cmdName: "cellalignment",
        value: {align: "left", vAlign: "middle"}
      }, {cmdName: "cellalignment", value: {align: "center", vAlign: "middle"}}, {cmdName: "cellalignment", value: {align: "right", vAlign: "middle"}}, {cmdName: "cellalignment", value: {align: "left", vAlign: "bottom"}}, {
        cmdName: "cellalignment",
        value: {align: "center", vAlign: "bottom"}
      }, {cmdName: "cellalignment", value: {align: "right", vAlign: "bottom"}}]
    }, {
      group: lang.aligntable,
      icon: "aligntable",
      subMenu: [{cmdName: "tablealignment", className: "left", label: lang.tableleft, value: "left"}, {cmdName: "tablealignment", className: "center", label: lang.tablecenter, value: "center"}, {
        cmdName: "tablealignment",
        className: "right",
        label: lang.tableright,
        value: "right"
      }]
    }, "-", {label: lang.insertparagraphbefore, cmdName: "insertparagraph", value: true}, {label: lang.insertparagraphafter, cmdName: "insertparagraph"}, {label: lang["copy"], cmdName: "copy"}, {label: lang["paste"], cmdName: "paste"}];
    if (!items.length) {
      return
    }
    var uiUtils = UE.ui.uiUtils;
    me.addListener("contextmenu", function (type, evt) {
      var offset = uiUtils.getViewportOffsetByEvent(evt);
      me.fireEvent("beforeselectionchange");
      if (menu) {
        menu.destroy()
      }
      for (var i = 0, ti, contextItems = []; ti = items[i]; i++) {
        var last;
        (function (item) {
          if (item == "-") {
            if ((last = contextItems[contextItems.length - 1]) && last !== "-") {
              contextItems.push("-")
            }
          } else if (item.hasOwnProperty("group")) {
            for (var j = 0, cj, subMenu = []; cj = item.subMenu[j]; j++) {
              (function (subItem) {
                if (subItem == "-") {
                  if ((last = subMenu[subMenu.length - 1]) && last !== "-") {
                    subMenu.push("-")
                  } else {
                    subMenu.splice(subMenu.length - 1)
                  }
                } else {
                  if ((me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) && (subItem.query ? subItem.query() : me.queryCommandState(subItem.cmdName)) > -1) {
                    subMenu.push({
                      label: subItem.label || me.getLang("contextMenu." + subItem.cmdName + (subItem.value || "")) || "",
                      className: "edui-for-" + subItem.cmdName + (subItem.className ? " edui-for-" + subItem.cmdName + "-" + subItem.className : ""),
                      onclick: subItem.exec ? function () {
                        subItem.exec.call(me)
                      } : function () {
                        me.execCommand(subItem.cmdName, subItem.value)
                      }
                    })
                  }
                }
              })(cj)
            }
            if (subMenu.length) {
              function getLabel() {
                switch (item.icon) {
                  case"table":
                    return me.getLang("contextMenu.table");
                  case"justifyjustify":
                    return me.getLang("contextMenu.paragraph");
                  case"aligntd":
                    return me.getLang("contextMenu.aligntd");
                  case"aligntable":
                    return me.getLang("contextMenu.aligntable");
                  case"tablesort":
                    return lang.tablesort;
                  case"borderBack":
                    return lang.borderbk;
                  default:
                    return ""
                }
              }

              contextItems.push({label: getLabel(), className: "edui-for-" + item.icon, subMenu: {items: subMenu, editor: me}})
            }
          } else {
            if ((me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) && (item.query ? item.query.call(me) : me.queryCommandState(item.cmdName)) > -1) {
              contextItems.push({
                label: item.label || me.getLang("contextMenu." + item.cmdName), className: "edui-for-" + (item.icon ? item.icon : item.cmdName + (item.value || "")), onclick: item.exec ? function () {
                  item.exec.call(me)
                } : function () {
                  me.execCommand(item.cmdName, item.value)
                }
              })
            }
          }
        })(ti)
      }
      if (contextItems[contextItems.length - 1] == "-") {
        contextItems.pop()
      }
      menu = new UE.ui.Menu({items: contextItems, className: "edui-contextmenu", editor: me});
      menu.render();
      menu.showAt(offset);
      me.fireEvent("aftershowcontextmenu", menu);
      domUtils.preventDefault(evt);
      if (browser.ie) {
        var ieRange;
        try {
          ieRange = me.selection.getNative().createRange()
        } catch (e) {
          return
        }
        if (ieRange.item) {
          var range = new dom.Range(me.document);
          range.selectNode(ieRange.item(0)).select(true, true)
        }
      }
    });
    me.addListener("aftershowcontextmenu", function (type, menu) {
      if (me.zeroclipboard) {
        var items = menu.items;
        for (var key in items) {
          if (items[key].className == "edui-for-copy") {
            me.zeroclipboard.clip(items[key].getDom())
          }
        }
      }
    })
  };
  UE.plugins["shortcutmenu"] = function () {
    var me = this, menu, items = me.options.shortcutMenu || [];
    if (!items.length) {
      return
    }
    me.addListener("mouseup", function (type, e) {
      var me = this, customEvt = {type: type, target: e.target || e.srcElement, screenX: e.screenX, screenY: e.screenY, clientX: e.clientX, clientY: e.clientY};
      setTimeout(function () {
        if (!menu) {
          menu = new baidu.editor.ui.ShortCutMenu({editor: me, items: items.concat([]), theme: me.options.theme, className: "edui-shortcutmenu"});
          menu.render();
          me.fireEvent("afterrendershortcutmenu", menu)
        }
        menu.show(customEvt, !!UE.plugins["contextmenu"])
      });
      if (type === "contextmenu") {
        domUtils.preventDefault(e);
        if (browser.ie9below) {
          var ieRange;
          try {
            ieRange = me.selection.getNative().createRange()
          } catch (e) {
            return
          }
          if (ieRange.item) {
            var range = new dom.Range(me.document);
            range.selectNode(ieRange.item(0)).select(true, true)
          }
        }
      }
    });
    me.addListener("keydown", function (type) {
      if (type === "keydown") {
        menu && !menu.isHidden && menu.hide()
      }
    })
  };
  UE.plugins["basestyle"] = function () {
    var basestyles = {bold: ["strong", "b"], italic: ["em", "i"], subscript: ["sub"], superscript: ["sup"]}, getObj = function (editor, tagNames) {
      return domUtils.filterNodeList(editor.selection.getStartElementPath(), tagNames)
    }, me = this;
    me.addshortcutkey({Bold: "ctrl+66", Italic: "ctrl+73", Underline: "ctrl+85"});
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName("b i"), function (node) {
        switch (node.tagName) {
          case"b":
            node.tagName = "strong";
            break;
          case"i":
            node.tagName = "em"
        }
      })
    });
    for (var style in basestyles) {
      (function (cmd, tagNames) {
        me.commands[cmd] = {
          execCommand: function (cmdName) {
            var range = me.selection.getRange(), obj = getObj(this, tagNames);
            if (range.collapsed) {
              if (obj) {
                var tmpText = me.document.createTextNode("");
                range.insertNode(tmpText).removeInlineStyle(tagNames);
                range.setStartBefore(tmpText);
                domUtils.remove(tmpText)
              } else {
                var tmpNode = range.document.createElement(tagNames[0]);
                if (cmdName == "superscript" || cmdName == "subscript") {
                  tmpText = me.document.createTextNode("");
                  range.insertNode(tmpText).removeInlineStyle(["sub", "sup"]).setStartBefore(tmpText).collapse(true)
                }
                range.insertNode(tmpNode).setStart(tmpNode, 0)
              }
              range.collapse(true)
            } else {
              if (cmdName == "superscript" || cmdName == "subscript") {
                if (!obj || obj.tagName.toLowerCase() != cmdName) {
                  range.removeInlineStyle(["sub", "sup"])
                }
              }
              obj ? range.removeInlineStyle(tagNames) : range.applyInlineStyle(tagNames[0])
            }
            range.select()
          }, queryCommandState: function () {
            return getObj(this, tagNames) ? 1 : 0
          }
        }
      })(style, basestyles[style])
    }
  };
  UE.plugins["elementpath"] = function () {
    var currentLevel, tagNames, me = this;
    me.setOpt("elementPathEnabled", true);
    if (!me.options.elementPathEnabled) {
      return
    }
    me.commands["elementpath"] = {
      execCommand: function (cmdName, level) {
        var start = tagNames[level], range = me.selection.getRange();
        currentLevel = level * 1;
        range.selectNode(start).select()
      }, queryCommandValue: function () {
        var parents = [].concat(this.selection.getStartElementPath()).reverse(), names = [];
        tagNames = parents;
        for (var i = 0, ci; ci = parents[i]; i++) {
          if (ci.nodeType == 3) {
            continue
          }
          var name = ci.tagName.toLowerCase();
          if (name == "img" && ci.getAttribute("anchorname")) {
            name = "anchor"
          }
          names[i] = name;
          if (currentLevel == i) {
            currentLevel = -1;
            break
          }
        }
        return names
      }
    }
  };
  UE.plugins["formatmatch"] = function () {
    var me = this, list = [], img, flag = 0;
    me.addListener("reset", function () {
      list = [];
      flag = 0
    });

    function addList(type, evt) {
      if (browser.webkit) {
        var target = evt.target.tagName == "IMG" ? evt.target : null
      }

      function addFormat(range) {
        if (text) {
          range.selectNode(text)
        }
        return range.applyInlineStyle(list[list.length - 1].tagName, null, list)
      }

      me.undoManger && me.undoManger.save();
      var range = me.selection.getRange(), imgT = target || range.getClosedNode();
      if (img && imgT && imgT.tagName == "IMG") {
        imgT.style.cssText += ";float:" + (img.style.cssFloat || img.style.styleFloat || "none") + ";display:" + (img.style.display || "inline");
        img = null
      } else {
        if (!img) {
          var collapsed = range.collapsed;
          if (collapsed) {
            var text = me.document.createTextNode("match");
            range.insertNode(text).select()
          }
          me.__hasEnterExecCommand = true;
          var removeFormatAttributes = me.options.removeFormatAttributes;
          me.options.removeFormatAttributes = "";
          me.execCommand("removeformat");
          me.options.removeFormatAttributes = removeFormatAttributes;
          me.__hasEnterExecCommand = false;
          range = me.selection.getRange();
          if (list.length) {
            addFormat(range)
          }
          if (text) {
            range.setStartBefore(text).collapse(true)
          }
          range.select();
          text && domUtils.remove(text)
        }
      }
      me.undoManger && me.undoManger.save();
      me.removeListener("mouseup", addList);
      flag = 0
    }

    me.commands["formatmatch"] = {
      execCommand: function (cmdName) {
        if (flag) {
          flag = 0;
          list = [];
          me.removeListener("mouseup", addList);
          return
        }
        var range = me.selection.getRange();
        img = range.getClosedNode();
        if (!img || img.tagName != "IMG") {
          range.collapse(true).shrinkBoundary();
          var start = range.startContainer;
          list = domUtils.findParents(start, true, function (node) {
            return !domUtils.isBlockElm(node) && node.nodeType == 1
          });
          for (var i = 0, ci; ci = list[i]; i++) {
            if (ci.tagName == "A") {
              list.splice(i, 1);
              break
            }
          }
        }
        me.addListener("mouseup", addList);
        flag = 1
      }, queryCommandState: function () {
        return flag
      }, notNeedUndo: 1
    }
  };
  UE.plugin.register("searchreplace", function () {
    var me = this;
    var _blockElm = {table: 1, tbody: 1, tr: 1, ol: 1, ul: 1};
    var lastRng = null;

    function getText(node) {
      var text = node.nodeType == 3 ? node.nodeValue : node[browser.ie ? "innerText" : "textContent"];
      return text.replace(domUtils.fillChar, "")
    }

    function findTextInString(textContent, opt, currentIndex) {
      var str = opt.searchStr;
      var reg = new RegExp(str, "g" + (opt.casesensitive ? "" : "i")), match;
      if (opt.dir == -1) {
        textContent = textContent.substr(0, currentIndex);
        textContent = textContent.split("").reverse().join("");
        str = str.split("").reverse().join("");
        match = reg.exec(textContent);
        if (match) {
          return currentIndex - match.index - str.length
        }
      } else {
        textContent = textContent.substr(currentIndex);
        match = reg.exec(textContent);
        if (match) {
          return match.index + currentIndex
        }
      }
      return -1
    }

    function findTextBlockElm(node, currentIndex, opt) {
      var textContent, index, methodName = opt.all || opt.dir == 1 ? "getNextDomNode" : "getPreDomNode";
      if (domUtils.isBody(node)) {
        node = node.firstChild
      }
      var first = 1;
      while (node) {
        textContent = getText(node);
        index = findTextInString(textContent, opt, currentIndex);
        first = 0;
        if (index != -1) {
          return {node: node, index: index}
        }
        node = domUtils[methodName](node);
        while (node && _blockElm[node.nodeName.toLowerCase()]) {
          node = domUtils[methodName](node, true)
        }
        if (node) {
          currentIndex = opt.dir == -1 ? getText(node).length : 0
        }
      }
    }

    function findNTextInBlockElm(node, index, str) {
      var currentIndex = 0, currentNode = node.firstChild, currentNodeLength = 0, result;
      while (currentNode) {
        if (currentNode.nodeType == 3) {
          currentNodeLength = getText(currentNode).replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, "").length;
          currentIndex += currentNodeLength;
          if (currentIndex >= index) {
            return {node: currentNode, index: currentNodeLength - (currentIndex - index)}
          }
        } else if (!dtd.$empty[currentNode.tagName]) {
          currentNodeLength = getText(currentNode).replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, "").length;
          currentIndex += currentNodeLength;
          if (currentIndex >= index) {
            result = findNTextInBlockElm(currentNode, currentNodeLength - (currentIndex - index), str);
            if (result) {
              return result
            }
          }
        }
        currentNode = domUtils.getNextDomNode(currentNode)
      }
    }

    function searchReplace(me, opt) {
      var rng = lastRng || me.selection.getRange(), startBlockNode, searchStr = opt.searchStr, span = me.document.createElement("span");
      span.innerHTML = "$$ueditor_searchreplace_key$$";
      rng.shrinkBoundary(true);
      if (!rng.collapsed) {
        rng.select();
        var rngText = me.selection.getText();
        if (new RegExp("^" + opt.searchStr + "$", opt.casesensitive ? "" : "i").test(rngText)) {
          if (opt.replaceStr != undefined) {
            replaceText(rng, opt.replaceStr);
            rng.select();
            return true
          } else {
            rng.collapse(opt.dir == -1)
          }
        }
      }
      rng.insertNode(span);
      rng.enlargeToBlockElm(true);
      startBlockNode = rng.startContainer;
      var currentIndex = getText(startBlockNode).indexOf("$$ueditor_searchreplace_key$$");
      rng.setStartBefore(span);
      domUtils.remove(span);
      var result = findTextBlockElm(startBlockNode, currentIndex, opt);
      if (result) {
        var rngStart = findNTextInBlockElm(result.node, result.index, searchStr);
        var rngEnd = findNTextInBlockElm(result.node, result.index + searchStr.length, searchStr);
        rng.setStart(rngStart.node, rngStart.index).setEnd(rngEnd.node, rngEnd.index);
        if (opt.replaceStr !== undefined) {
          replaceText(rng, opt.replaceStr)
        }
        rng.select();
        return true
      } else {
        rng.setCursor()
      }
    }

    function replaceText(rng, str) {
      str = me.document.createTextNode(str);
      rng.deleteContents().insertNode(str)
    }

    return {
      commands: {
        searchreplace: {
          execCommand: function (cmdName, opt) {
            utils.extend(opt, {all: false, casesensitive: false, dir: 1}, true);
            var num = 0;
            if (opt.all) {
              lastRng = null;
              var rng = me.selection.getRange(), first = me.body.firstChild;
              if (first && first.nodeType == 1) {
                rng.setStart(first, 0);
                rng.shrinkBoundary(true)
              } else if (first.nodeType == 3) {
                rng.setStartBefore(first)
              }
              rng.collapse(true).select(true);
              if (opt.replaceStr !== undefined) {
                me.fireEvent("saveScene")
              }
              while (searchReplace(this, opt)) {
                num++;
                lastRng = me.selection.getRange();
                lastRng.collapse(opt.dir == -1)
              }
              if (num) {
                me.fireEvent("saveScene")
              }
            } else {
              if (opt.replaceStr !== undefined) {
                me.fireEvent("saveScene")
              }
              if (searchReplace(this, opt)) {
                num++;
                lastRng = me.selection.getRange();
                lastRng.collapse(opt.dir == -1)
              }
              if (num) {
                me.fireEvent("saveScene")
              }
            }
            return num
          }, notNeedUndo: 1
        }
      }, bindEvents: {
        clearlastSearchResult: function () {
          lastRng = null
        }
      }
    }
  });
  UE.plugins["customstyle"] = function () {
    var me = this;
    me.setOpt({
      customstyle: [{tag: "h1", name: "tc", style: "font-size:32px;line-height:40px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;"}, {
        tag: "h1",
        name: "tl",
        style: "font-size:32px;line-height:40px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;"
      }, {tag: "span", name: "im", style: "font-size:16px;font-style:italic;font-weight:bold;line-height:18px;"}, {tag: "span", name: "hi", style: "font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;"}]
    });
    me.commands["customstyle"] = {
      execCommand: function (cmdName, obj) {
        var me = this, tagName = obj.tag, node = domUtils.findParent(me.selection.getStart(), function (node) {
          return node.getAttribute("label")
        }, true), range, bk, tmpObj = {};
        for (var p in obj) {
          if (obj[p] !== undefined) tmpObj[p] = obj[p]
        }
        delete tmpObj.tag;
        if (node && node.getAttribute("label") == obj.label) {
          range = this.selection.getRange();
          bk = range.createBookmark();
          if (range.collapsed) {
            if (dtd.$block[node.tagName]) {
              var fillNode = me.document.createElement("p");
              domUtils.moveChild(node, fillNode);
              node.parentNode.insertBefore(fillNode, node);
              domUtils.remove(node)
            } else {
              domUtils.remove(node, true)
            }
          } else {
            var common = domUtils.getCommonAncestor(bk.start, bk.end), nodes = domUtils.getElementsByTagName(common, tagName);
            if (new RegExp(tagName, "i").test(common.tagName)) {
              nodes.push(common)
            }
            for (var i = 0, ni; ni = nodes[i++];) {
              if (ni.getAttribute("label") == obj.label) {
                var ps = domUtils.getPosition(ni, bk.start), pe = domUtils.getPosition(ni, bk.end);
                if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) && (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)) if (dtd.$block[tagName]) {
                  var fillNode = me.document.createElement("p");
                  domUtils.moveChild(ni, fillNode);
                  ni.parentNode.insertBefore(fillNode, ni)
                }
                domUtils.remove(ni, true)
              }
            }
            node = domUtils.findParent(common, function (node) {
              return node.getAttribute("label") == obj.label
            }, true);
            if (node) {
              domUtils.remove(node, true)
            }
          }
          range.moveToBookmark(bk).select()
        } else {
          if (dtd.$block[tagName]) {
            this.execCommand("paragraph", tagName, tmpObj, "customstyle");
            range = me.selection.getRange();
            if (!range.collapsed) {
              range.collapse();
              node = domUtils.findParent(me.selection.getStart(), function (node) {
                return node.getAttribute("label") == obj.label
              }, true);
              var pNode = me.document.createElement("p");
              domUtils.insertAfter(node, pNode);
              domUtils.fillNode(me.document, pNode);
              range.setStart(pNode, 0).setCursor()
            }
          } else {
            range = me.selection.getRange();
            if (range.collapsed) {
              node = me.document.createElement(tagName);
              domUtils.setAttributes(node, tmpObj);
              range.insertNode(node).setStart(node, 0).setCursor();
              return
            }
            bk = range.createBookmark();
            range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select()
          }
        }
      }, queryCommandValue: function () {
        var parent = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) {
          return node.getAttribute("label")
        });
        return parent ? parent.getAttribute("label") : ""
      }
    };
    me.addListener("keyup", function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 32 || keyCode == 13) {
        var range = me.selection.getRange();
        if (range.collapsed) {
          var node = domUtils.findParent(me.selection.getStart(), function (node) {
            return node.getAttribute("label")
          }, true);
          if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) {
            var p = me.document.createElement("p");
            domUtils.insertAfter(node, p);
            domUtils.fillNode(me.document, p);
            domUtils.remove(node);
            range.setStart(p, 0).setCursor()
          }
        }
      }
    })
  };
  UE.plugins["catchremoteimage"] = function () {
    var me = this, ajax = UE.ajax;
    if (me.options.catchRemoteImageEnable === false) {
      return
    }
    me.setOpt({catchRemoteImageEnable: false});
    var catcherLocalDomain = me.getOpt("catcherLocalDomain"), catcherActionUrl = me.getActionUrl(me.getOpt("catcherActionName")), catcherUrlPrefix = me.getOpt("catcherUrlPrefix"), catcherFieldName = me.getOpt("catcherFieldName");
    me.addListener("serverConfigLoaded", function () {
      catcherLocalDomain = me.getOpt("catcherLocalDomain");
      catcherActionUrl = me.getActionUrl(me.getOpt("catcherActionName"));
      catcherUrlPrefix = me.getOpt("catcherUrlPrefix");
      catcherFieldName = me.getOpt("catcherFieldName")
    });
    me.addListener("afterpaste", function () {
      me.fireEvent("catchremoteimage")
    });
    var catchRemoteImageCatching = false;

    function sendApi(imgs, callbacks) {
      var params = utils.serializeParam(me.queryCommandValue("serverparam")) || "", url = utils.formatUrl(catcherActionUrl + (catcherActionUrl.indexOf("?") === -1 ? "?" : "&") + params), isJsonp = utils.isCrossDomainUrl(url),
        opt = {method: "POST", dataType: isJsonp ? "jsonp" : "", timeout: 6e4, headers: me.options.serverHeaders || {}, onsuccess: callbacks["success"], onerror: callbacks["error"]};
      opt[catcherFieldName] = imgs;
      ajax.request(url, opt)
    }

    function catchElement(type, ele, imageUrl) {
      sendApi([imageUrl], {
        success: function (r) {
          try {
            var info = r.state !== undefined ? r : eval("(" + r.responseText + ")")
          } catch (e) {
            return
          }
          info = me.options.serverResponsePrepare(info);
          var oldSrc, newSrc, oldBgIMG, newBgIMG, list = info.list;
          var catchFailList = [];
          var catchSuccessList = [];
          var failIMG = me.options.themePath + me.options.theme + "/images/img-cracked.png";
          var loadingIMG = me.options.themePath + me.options.theme + "/images/spacer.gif";
          var cj = list[0];
          switch (type) {
            case"image":
              oldSrc = ele.getAttribute("_src") || ele.src || "";
              if (cj.state === "SUCCESS") {
                newSrc = catcherUrlPrefix + cj.url;
                domUtils.removeClasses(ele, "uep-loading");
                domUtils.setAttributes(ele, {src: newSrc, _src: newSrc, "data-catch-result": "success"});
                catchSuccessList.push(ele)
              } else {
                domUtils.removeClasses(ele, "uep-loading");
                domUtils.setAttributes(ele, {src: failIMG, _src: failIMG, "data-catch-result": "fail"});
                catchFailList.push(ele)
              }
              break;
            case"background":
              oldBgIMG = ele.getAttribute("data-background") || "";
              if (cj.state === "SUCCESS") {
                newBgIMG = catcherUrlPrefix + cj.url;
                ele.style.cssText = ele.style.cssText.replace(loadingIMG, newBgIMG);
                domUtils.removeAttributes(ele, "data-background");
                domUtils.setAttributes(ele, {"data-catch-result": "success"});
                catchSuccessList.push(ele)
              } else {
                ele.style.cssText = ele.style.cssText.replace(loadingIMG, failIMG);
                domUtils.removeAttributes(ele, "data-background");
                domUtils.setAttributes(ele, {"data-catch-result": "fail"});
                catchFailList.push(ele)
              }
              break
          }
          me.fireEvent("catchremotesuccess", catchSuccessList, catchFailList);
          catchRemoteImageCatching = false;
          setTimeout(function () {
            me.fireEvent("catchremoteimage")
          }, 0)
        }, error: function () {
          me.fireEvent("catchremoteerror");
          catchRemoteImageCatching = false;
          setTimeout(function () {
            me.fireEvent("catchremoteimage")
          }, 0)
        }
      })
    }

    function catchRemoteImage() {
      if (catchRemoteImageCatching) {
        return
      }
      catchRemoteImageCatching = true;
      var loadingIMG = me.options.themePath + me.options.theme + "/images/spacer.gif", imgs = me.document.querySelectorAll('[style*="url"],img'), test = function (src, urls) {
        if (src.indexOf(location.host) !== -1 || /(^\.)|(^\/)/.test(src)) {
          return true
        }
        if (urls) {
          for (var j = 0, url; url = urls[j++];) {
            if (src.indexOf(url) !== -1) {
              return true
            }
          }
        }
        return false
      };
      for (var i = 0, ci; ci = imgs[i++];) {
        if (ci.getAttribute("data-word-image") || ci.getAttribute("data-catch-result") || ci.getAttribute("data-formula-image")) {
          continue
        }
        if (ci.nodeName === "IMG") {
          var src = ci.getAttribute("_src") || ci.src || "";
          if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) {
            catchElement("image", ci, src);
            domUtils.setAttributes(ci, {class: "uep-loading", _src: src, src: loadingIMG});
            return
          }
        } else {
          var backgroundImageurl = ci.style.cssText.replace(/.*\s?url\([\'\"]?/, "").replace(/[\'\"]?\).*/, "");
          if (/^(https?|ftp):/i.test(backgroundImageurl) && !test(backgroundImageurl, catcherLocalDomain)) {
            catchElement("background", ci, backgroundImageurl);
            ci.style.cssText = ci.style.cssText.replace(backgroundImageurl, loadingIMG);
            domUtils.setAttributes(ci, {"data-background": backgroundImageurl});
            return
          }
        }
      }
      catchRemoteImageCatching = false
    }

    me.addListener("catchremoteimage", function () {
      catchRemoteImage()
    })
  };
  UE.commands["insertparagraph"] = {
    execCommand: function (cmdName, front) {
      var me = this, range = me.selection.getRange(), start = range.startContainer, tmpNode;
      while (start) {
        if (domUtils.isBody(start)) {
          break
        }
        tmpNode = start;
        start = start.parentNode
      }
      if (tmpNode) {
        var p = me.document.createElement("p");
        if (front) {
          tmpNode.parentNode.insertBefore(p, tmpNode)
        } else {
          tmpNode.parentNode.insertBefore(p, tmpNode.nextSibling)
        }
        domUtils.fillNode(me.document, p);
        range.setStart(p, 0).setCursor(false, true)
      }
    }
  };
  UE.plugins["template"] = function () {
    UE.commands["template"] = {
      execCommand: function (cmd, obj) {
        obj.html && this.execCommand("inserthtml", obj.html)
      }
    };
    this.addListener("click", function (type, evt) {
      var el = evt.target || evt.srcElement, range = this.selection.getRange();
      var tnode = domUtils.findParent(el, function (node) {
        if (node.className && domUtils.hasClass(node, "ue_t")) {
          return node
        }
      }, true);
      tnode && range.selectNode(tnode).shrinkBoundary().select()
    });
    this.addListener("keydown", function (type, evt) {
      var range = this.selection.getRange();
      if (!range.collapsed) {
        if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
          var tnode = domUtils.findParent(range.startContainer, function (node) {
            if (node.className && domUtils.hasClass(node, "ue_t")) {
              return node
            }
          }, true);
          if (tnode) {
            domUtils.removeClasses(tnode, ["ue_t"])
          }
        }
      }
    })
  };
  UE.plugin.register("autoupload", function () {
    function sendAndInsertFile(file, editor) {
      var me = editor;
      var fieldName, urlPrefix, maxSize, allowFiles, actionUrl, loadingHtml, errorHandler, successHandler, filetype = /image\/\w+/i.test(file.type) ? "image" : "file", loadingId = "loading_" + (+new Date).toString(36);
      fieldName = me.getOpt(filetype + "FieldName");
      urlPrefix = me.getOpt(filetype + "UrlPrefix");
      maxSize = me.getOpt(filetype + "MaxSize");
      allowFiles = me.getOpt(filetype + "AllowFiles");
      actionUrl = me.getActionUrl(me.getOpt(filetype + "ActionName"));
      errorHandler = function (title) {
        var loader = me.document.getElementById(loadingId);
        loader && domUtils.remove(loader);
        me.fireEvent("showmessage", {id: loadingId, content: title, type: "error", timeout: 4e3})
      };
      if (filetype === "image") {
        loadingHtml = '<img class="uep-loading" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif">';
        successHandler = function (data) {
          var link = urlPrefix + data.url, loader = me.document.getElementById(loadingId);
          if (loader) {
            domUtils.removeClasses(loader, "uep-loading");
            loader.setAttribute("src", link);
            loader.setAttribute("_src", link);
            loader.setAttribute("alt", data.original || "");
            loader.removeAttribute("id");
            me.trigger("contentchange", loader)
          }
        }
      } else {
        loadingHtml = "<p>" + '<img class="uep-loading" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif">' + "</p>";
        successHandler = function (data) {
          var link = urlPrefix + data.url, loader = me.document.getElementById(loadingId);
          var rng = me.selection.getRange(), bk = rng.createBookmark();
          rng.selectNode(loader).select();
          me.execCommand("insertfile", {url: link});
          rng.moveToBookmark(bk).select()
        }
      }
      me.execCommand("inserthtml", loadingHtml);
      if (!me.getOpt(filetype + "ActionName")) {
        errorHandler(me.getLang("autoupload.errorLoadConfig"));
        return
      }
      if (file.size > maxSize) {
        errorHandler(me.getLang("autoupload.exceedSizeError"));
        return
      }
      var fileext = file.name ? file.name.substr(file.name.lastIndexOf(".")) : "";
      if (fileext && filetype != "image" || allowFiles && (allowFiles.join("") + ".").indexOf(fileext.toLowerCase() + ".") == -1) {
        errorHandler(me.getLang("autoupload.exceedTypeError"));
        return
      }
      var upload = function (file) {
        const formData = new FormData;
        formData.append(fieldName, file, file.name);
        UE.api.requestAction(me, me.getOpt(filetype + "ActionName"), {data: formData}).then(function (res) {
          successHandler(res.data)
        }).catch(function (err) {
          errorHandler(me.getLang("autoupload.loadError"))
        })
      };
      var imageCompressEnable = me.getOpt("imageCompressEnable"), imageMaxSize = me.getOpt("imageMaxSize"), imageCompressBorder = me.getOpt("imageCompressBorder");
      if ("image" === filetype && imageCompressEnable) {
        UE.image.compress(file, {maxSizeMB: imageMaxSize / 1024 / 1024, maxWidthOrHeight: imageCompressBorder}).then(function (compressedFile) {
          if (me.options.debug) {
            console.log("AutoUpload.CompressImage", (compressedFile.size / file.size * 100).toFixed(2) + "%")
          }
          upload(compressedFile)
        }).catch(function (err) {
          console.error("AutoUpload.CompressImage.error", err);
          upload(file)
        })
      } else {
        upload(file)
      }
    }

    function getPasteImage(e) {
      return e.clipboardData && e.clipboardData.items && e.clipboardData.items.length == 1 && /^image\//.test(e.clipboardData.items[0].type) ? e.clipboardData.items : null
    }

    function getDropImage(e) {
      return e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files : null
    }

    return {
      outputRule: function (root) {
        utils.each(root.getNodesByTagName("img"), function (n) {
          if (/\b(uep\-loading\-error)|(bloaderrorclass)\b/.test(n.getAttr("class"))) {
            n.parentNode.removeChild(n)
          }
        });
        utils.each(root.getNodesByTagName("p"), function (n) {
          if (/\bloadpara\b/.test(n.getAttr("class"))) {
            n.parentNode.removeChild(n)
          }
        })
      }, bindEvents: {
        defaultOptions: {enableDragUpload: true, enablePasteUpload: true}, ready: function (e) {
          var me = this;
          if (window.FormData && window.FileReader) {
            var handler = function (e) {
              var hasImg = false, items;
              items = e.type == "paste" ? getPasteImage(e) : getDropImage(e);
              if (items) {
                var len = items.length, file;
                while (len--) {
                  file = items[len];
                  if (file.getAsFile) file = file.getAsFile();
                  if (file && file.size > 0) {
                    sendAndInsertFile(file, me);
                    hasImg = true
                  }
                }
                hasImg && e.preventDefault()
              }
            };
            if (me.getOpt("enablePasteUpload") !== false) {
              domUtils.on(me.body, "paste ", handler)
            }
            if (me.getOpt("enableDragUpload") !== false) {
              domUtils.on(me.body, "drop", handler);
              domUtils.on(me.body, "dragover", function (e) {
                if (e.dataTransfer.types[0] == "Files") {
                  e.preventDefault()
                }
              })
            } else {
              if (browser.gecko) {
                domUtils.on(me.body, "drop", function (e) {
                  if (getDropImage(e)) {
                    e.preventDefault()
                  }
                })
              }
            }
            utils.cssRule("loading", ".uep-loading{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loading.gif') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-left:1px;height:22px;width:22px;}\n" + ".uep-loading-error{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loaderror.png') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-right:1px;height:22px;width:22px;" + "}", this.document)
          }
        }
      }
    }
  });
  UE.plugin.register("section", function () {
    function Section(option) {
      this.tag = "";
      this.level = -1, this.dom = null;
      this.nextSection = null;
      this.previousSection = null;
      this.parentSection = null;
      this.startAddress = [];
      this.endAddress = [];
      this.children = []
    }

    function getSection(option) {
      var section = new Section;
      return utils.extend(section, option)
    }

    function getNodeFromAddress(startAddress, root) {
      var current = root;
      for (var i = 0; i < startAddress.length; i++) {
        if (!current.childNodes) return null;
        current = current.childNodes[startAddress[i]]
      }
      return current
    }

    var me = this;
    return {
      bindMultiEvents: {
        type: "aftersetcontent afterscencerestore", handler: function () {
          me.fireEvent("updateSections")
        }
      }, bindEvents: {
        ready: function () {
          me.fireEvent("updateSections");
          domUtils.on(me.body, "drop paste", function () {
            me.fireEvent("updateSections")
          })
        }, afterexeccommand: function (type, cmd) {
          if (cmd == "paragraph") {
            me.fireEvent("updateSections")
          }
        }, keyup: function (type, e) {
          var me = this, range = me.selection.getRange();
          if (range.collapsed != true) {
            me.fireEvent("updateSections")
          } else {
            var keyCode = e.keyCode || e.which;
            if (keyCode == 13 || keyCode == 8 || keyCode == 46) {
              me.fireEvent("updateSections")
            }
          }
        }
      }, commands: {
        getsections: {
          execCommand: function (cmd, levels) {
            var levelFn = levels || ["h1", "h2", "h3", "h4", "h5", "h6"];
            for (var i = 0; i < levelFn.length; i++) {
              if (typeof levelFn[i] == "string") {
                levelFn[i] = function (fn) {
                  return function (node) {
                    return node.tagName == fn.toUpperCase()
                  }
                }(levelFn[i])
              } else if (typeof levelFn[i] != "function") {
                levelFn[i] = function (node) {
                  return null
                }
              }
            }

            function getSectionLevel(node) {
              for (var i = 0; i < levelFn.length; i++) {
                if (levelFn[i](node)) return i
              }
              return -1
            }

            var me = this, Directory = getSection({level: -1, title: "root"}), previous = Directory;

            function traversal(node, Directory) {
              var level, tmpSection = null, parent, child, children = node.childNodes;
              for (var i = 0, len = children.length; i < len; i++) {
                child = children[i];
                level = getSectionLevel(child);
                if (level >= 0) {
                  var address = me.selection.getRange().selectNode(child).createAddress(true).startAddress,
                    current = getSection({tag: child.tagName, title: child.innerText || child.textContent || "", level: level, dom: child, startAddress: utils.clone(address, []), endAddress: utils.clone(address, []), children: []});
                  previous.nextSection = current;
                  current.previousSection = previous;
                  parent = previous;
                  while (level <= parent.level) {
                    parent = parent.parentSection
                  }
                  current.parentSection = parent;
                  parent.children.push(current);
                  tmpSection = previous = current
                } else {
                  child.nodeType === 1 && traversal(child, Directory);
                  tmpSection && tmpSection.endAddress[tmpSection.endAddress.length - 1]++
                }
              }
            }

            traversal(me.body, Directory);
            return Directory
          }, notNeedUndo: true
        }, movesection: {
          execCommand: function (cmd, sourceSection, targetSection, isAfter) {
            var me = this, targetAddress, target;
            if (!sourceSection || !targetSection || targetSection.level == -1) return;
            targetAddress = isAfter ? targetSection.endAddress : targetSection.startAddress;
            target = getNodeFromAddress(targetAddress, me.body);
            if (!targetAddress || !target || isContainsAddress(sourceSection.startAddress, sourceSection.endAddress, targetAddress)) return;
            var startNode = getNodeFromAddress(sourceSection.startAddress, me.body), endNode = getNodeFromAddress(sourceSection.endAddress, me.body), current, nextNode;
            if (isAfter) {
              current = endNode;
              while (current && !(domUtils.getPosition(startNode, current) & domUtils.POSITION_FOLLOWING)) {
                nextNode = current.previousSibling;
                domUtils.insertAfter(target, current);
                if (current == startNode) break;
                current = nextNode
              }
            } else {
              current = startNode;
              while (current && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
                nextNode = current.nextSibling;
                target.parentNode.insertBefore(current, target);
                if (current == endNode) break;
                current = nextNode
              }
            }
            me.fireEvent("updateSections");

            function isContainsAddress(startAddress, endAddress, addressTarget) {
              var isAfterStartAddress = false, isBeforeEndAddress = false;
              for (var i = 0; i < startAddress.length; i++) {
                if (i >= addressTarget.length) break;
                if (addressTarget[i] > startAddress[i]) {
                  isAfterStartAddress = true;
                  break
                } else if (addressTarget[i] < startAddress[i]) {
                  break
                }
              }
              for (var i = 0; i < endAddress.length; i++) {
                if (i >= addressTarget.length) break;
                if (addressTarget[i] < startAddress[i]) {
                  isBeforeEndAddress = true;
                  break
                } else if (addressTarget[i] > startAddress[i]) {
                  break
                }
              }
              return isAfterStartAddress && isBeforeEndAddress
            }
          }
        }, deletesection: {
          execCommand: function (cmd, section, keepChildren) {
            var me = this;
            if (!section) return;

            function getNodeFromAddress(startAddress) {
              var current = me.body;
              for (var i = 0; i < startAddress.length; i++) {
                if (!current.childNodes) return null;
                current = current.childNodes[startAddress[i]]
              }
              return current
            }

            var startNode = getNodeFromAddress(section.startAddress), endNode = getNodeFromAddress(section.endAddress), current = startNode, nextNode;
            if (!keepChildren) {
              while (current && domUtils.inDoc(endNode, me.document) && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
                nextNode = current.nextSibling;
                domUtils.remove(current);
                current = nextNode
              }
            } else {
              domUtils.remove(current)
            }
            me.fireEvent("updateSections")
          }
        }, selectsection: {
          execCommand: function (cmd, section) {
            if (!section && !section.dom) return false;
            var me = this, range = me.selection.getRange(), address = {startAddress: utils.clone(section.startAddress, []), endAddress: utils.clone(section.endAddress, [])};
            address.endAddress[address.endAddress.length - 1]++;
            range.moveToAddress(address).select().scrollToView();
            return true
          }, notNeedUndo: true
        }, scrolltosection: {
          execCommand: function (cmd, section) {
            if (!section && !section.dom) return false;
            var me = this, range = me.selection.getRange(), address = {startAddress: section.startAddress, endAddress: section.endAddress};
            address.endAddress[address.endAddress.length - 1]++;
            range.moveToAddress(address).scrollToView();
            return true
          }, notNeedUndo: true
        }
      }
    }
  });
  UE.plugin.register("simpleupload", function () {
    var me = this, isLoaded = false, containerBtn;

    function initUploadBtn() {
      var input = document.createElement("input");
      input.style.cssText = "position:absolute;top:0;left:0;width:100%;height:100%;cursor:pointer;font-size:0;opacity:0;";
      input.type = "file";
      input.accept = me.getOpt("imageAllowFiles").join(",");
      containerBtn.appendChild(input);
      domUtils.on(input, "click", function (e) {
        var toolbarCallback = me.getOpt("toolbarCallback");
        if (toolbarCallback) {
          if (true === toolbarCallback("simpleupload", me)) {
            e.stopPropagation();
            e.preventDefault()
          }
        }
      });
      domUtils.on(input, "change", function (e) {
        var state = me.queryCommandState("simpleupload");
        if (state === -1) {
          return
        }
        if (!input.value) {
          return
        }
        var loadingId = UE.dialog.loadingPlaceholder(me);
        if (!me.getOpt("imageActionName")) {
          UE.dialog.removeLoadingPlaceholder(me, loadingId);
          UE.dialog.tipError(me, me.getLang("autoupload.errorLoadConfig"));
          return
        }
        var allowFiles = me.getOpt("imageAllowFiles");
        var filename = input.value, fileext = filename ? filename.substr(filename.lastIndexOf(".")) : "";
        if (!fileext || allowFiles && (allowFiles.join("") + ".").indexOf(fileext.toLowerCase() + ".") === -1) {
          UE.dialog.removeLoadingPlaceholder(me, loadingId);
          UE.dialog.tipError(me, me.getLang("autoupload.exceedTypeError"));
          return
        }
        var upload = function (file) {
          const formData = new FormData;
          formData.append(me.getOpt("imageFieldName"), file, file.name);
          UE.api.requestAction(me, me.getOpt("imageActionName"), {data: formData}).then(function (res) {
            var resData = me.getOpt("serverResponsePrepare")(res.data);
            if ("SUCCESS" === resData.state && resData.url) {
              const loader = me.document.getElementById(loadingId);
              domUtils.removeClasses(loader, "uep-loading");
              const link = me.options.imageUrlPrefix + resData.url;
              loader.setAttribute("src", link);
              loader.setAttribute("_src", link);
              loader.setAttribute("alt", resData.original || "");
              loader.removeAttribute("id");
              me.fireEvent("contentchange");
              me.fireEvent("uploadsuccess", {res: resData, type: "image"})
            } else {
              UE.dialog.removeLoadingPlaceholder(me, loadingId);
              UE.dialog.tipError(me, resData.state)
            }
          }).catch(function (err) {
            UE.dialog.removeLoadingPlaceholder(me, loadingId);
            UE.dialog.tipError(me, err)
          })
        };
        var file = input.files[0];
        var imageCompressEnable = me.getOpt("imageCompressEnable"), imageMaxSize = me.getOpt("imageMaxSize"), imageCompressBorder = me.getOpt("imageCompressBorder");
        if (imageCompressEnable) {
          UE.image.compress(file, {maxSizeMB: imageMaxSize / 1024 / 1024, maxWidthOrHeight: imageCompressBorder}).then(function (compressedFile) {
            if (me.options.debug) {
              console.log("SimpleUpload.CompressImage", (compressedFile.size / file.size * 100).toFixed(2) + "%")
            }
            upload(compressedFile)
          }).catch(function (err) {
            console.error("SimpleUpload.CompressImage.error", err);
            upload(file)
          })
        } else {
          upload(file)
        }
      });
      var stateTimer;
      me.addListener("selectionchange", function () {
        clearTimeout(stateTimer);
        stateTimer = setTimeout(function () {
          var state = me.queryCommandState("simpleupload");
          if (state === -1) {
            input.disabled = "disabled"
          } else {
            input.disabled = false
          }
        }, 400)
      });
      isLoaded = true
    }

    return {
      bindEvents: {
        ready: function () {
          utils.cssRule("loading", ".uep-loading{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loading.gif') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-right:1px;height:22px;width:22px;}\n" + ".uep-loading-error{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loaderror.png') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-right:1px;height:22px;width:22px;" + "}", this.document)
        }, simpleuploadbtnready: function (type, container) {
          containerBtn = container;
          me.afterConfigReady(initUploadBtn)
        }
      }, outputRule: function (root) {
        utils.each(root.getNodesByTagName("img"), function (n) {
          if (/\b(uep\-loading\-error)|(bloaderrorclass)\b/.test(n.getAttr("class"))) {
            n.parentNode.removeChild(n)
          }
        })
      }, commands: {
        simpleupload: {
          queryCommandState: function () {
            return isLoaded ? 0 : -1
          }
        }
      }
    }
  });
  UE.plugin.register("serverparam", function () {
    var me = this, serverParam = {};
    return {
      commands: {
        serverparam: {
          execCommand: function (cmd, key, value) {
            if (key === undefined || key === null) {
              serverParam = {}
            } else if (utils.isString(key)) {
              if (value === undefined || value === null) {
                delete serverParam[key]
              } else {
                serverParam[key] = value
              }
            } else if (utils.isObject(key)) {
              utils.extend(serverParam, key, false)
            } else if (utils.isFunction(key)) {
              utils.extend(serverParam, key(), false)
            }
          }, queryCommandValue: function () {
            return serverParam || {}
          }
        }
      }
    }
  });
  UE.plugin.register("insertfile", function () {
    var me = this;

    function getFileIcon(url) {
      var ext = url.substr(url.lastIndexOf(".") + 1).toLowerCase(), maps = {
        ai: "ai.svg",
        apk: "apk.svg",
        chm: "chm.svg",
        css: "css.svg",
        doc: "doc.svg",
        docx: "docx.svg",
        dwg: "dwg.svg",
        gif: "gif.svg",
        html: "html.svg",
        jpeg: "jpeg.svg",
        jpg: "jpg.svg",
        log: "log.svg",
        mp3: "mp3.svg",
        mp4: "mp4.svg",
        pdf: "pdf.svg",
        png: "png.svg",
        ppt: "ppt.svg",
        pptx: "pptx.svg",
        psd: "psd.svg",
        rar: "rar.svg",
        svg: "svg.svg",
        torrent: "torrent.svg",
        txt: "txt.svg",
        unknown: "unknown.svg",
        xls: "xls.svg",
        xlsx: "xlsx.svg",
        zip: "zip.svg"
      };
      return maps[ext] ? maps[ext] : maps["unknown"]
    }

    return {
      commands: {
        insertfile: {
          execCommand: function (command, filelist) {
            filelist = utils.isArray(filelist) ? filelist : [filelist];
            if (me.fireEvent("beforeinsertfile", filelist) === true) {
              return
            }
            var i, item, icon, title, html = "", URL = me.getOpt("UEDITOR_HOME_URL"), iconDir = me.options.themePath + me.options.theme + "/exts/";
            for (i = 0; i < filelist.length; i++) {
              item = filelist[i];
              icon = iconDir + getFileIcon(item.url);
              title = item.title || item.url.substr(item.url.lastIndexOf("/") + 1);
              html += "<p>" + '<a style="background:#EEE;padding:10px;border-radius:5px;line-height:1.5em;display:inline-flex;align-items:center;" href="' + item.url + '" title="' + title + '" target="_blank">' + '<img style="vertical-align:middle;margin-right:0.5em;height:1.5em;" src="' + icon + '" _src="' + icon + '" />' + '<span style="color:#111111;line-height:1.5em;flex-grow:1;">' + title + "</span>" + "</a>" + "</p>"
            }
            me.execCommand("insertHtml", html);
            me.fireEvent("afterinsertfile", filelist)
          }
        }
      }
    }
  });
  UE.plugins["markdown-shortcut"] = function () {
    if (!UE.browser.chrome) {
      return
    }
    const me = this;
    const getCleanHtml = function (node) {
      let html = node.innerHTML;
      html = html.replace(/[\u200b]*/g, "");
      return html
    };
    let shortCuts = [];
    for (let i = 1; i <= 6; i++) {
      const regExp = new RegExp("^\\t?" + Array(i + 1).join("#") + "(\\s|&nbsp;)");
      (function (command) {
        shortCuts.push({
          name: "Head" + i, tagName: ["P"], key: [" "], offset: [i + 1, i + 2], match: [regExp], callback: function (param) {
            me.__hasEnterExecCommand = true;
            me.execCommand("paragraph", command);
            let range = me.selection.getRange();
            let node = range.startContainer;
            let html = getCleanHtml(node);
            html = html.replace(regExp, "");
            if (!html) {
              html = domUtils.fillChar
            }
            node.innerHTML = html;
            me.__hasEnterExecCommand = false
          }
        })
      })("h" + i)
    }
    me.on("ready", function () {
      domUtils.on(me.body, "keyup", function (e) {
        let range = me.selection.getRange();
        if (range.endOffset !== range.startOffset) {
          return
        }
        let key = e.key;
        let offset = range.startOffset;
        const node = range.startContainer.parentNode;
        let html = getCleanHtml(node);
        let tagName = node.tagName;
        for (let s of shortCuts) {
          if (!s.tagName.includes(tagName)) {
            continue
          }
          if (!s.key.includes(key)) {
            continue
          }
          if (!s.offset.includes(offset)) {
            continue
          }
          for (let m of s.match) {
            let match = html.match(m);
            if (match) {
              s.callback({node: node});
              break
            }
          }
        }
      })
    })
  };
  UE.plugins["quick-operate"] = function () {
    if (!UE.browser.chrome) {
      return
    }
    return;
    let me = this;
    const uiUtils = UE.ui.uiUtils;
    me.on("ready", function () {
      let quickOperate = new UE.ui.QuickOperate({className: "edui-quick-operate", editor: me});
      quickOperate.render();
      let quickOperateNode = {root: null, target: null};
      domUtils.on(quickOperate.el, "mouseenter", function (evt) {
        quickOperateNode.root && quickOperateNode.root.classList && quickOperateNode.root.classList.add("edui-quick-operate-active")
      });
      domUtils.on(quickOperate.el, "mouseleave", function (evt) {
        quickOperateNode.root && quickOperateNode.root.classList && quickOperateNode.root.classList.remove("edui-quick-operate-active")
      });
      domUtils.on(me.body, "mouseout", function (evt) {
      });
      domUtils.on(me.body, "mouseover", function (evt) {
        const node = evt.target;
        let rootNode = node;
        for (; rootNode.parentNode && rootNode.parentNode.tagName !== "BODY";) {
          rootNode = rootNode.parentNode
        }
        quickOperateNode.root = rootNode;
        quickOperateNode.target = node;
        const rect = node.getBoundingClientRect();
        const offset = uiUtils.getClientRect(node);
        offset.left = offset.left - 55;
        quickOperate.showAt(offset)
      })
    })
  };
  var baidu = baidu || {};
  baidu.editor = baidu.editor || {};
  UE.ui = baidu.editor.ui = {};
  (function () {
    var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils;
    var magic = "$EDITORUI";
    var root = window[magic] = {};
    var uidMagic = "ID" + magic;
    var uidCount = 0;
    var uiUtils = baidu.editor.ui.uiUtils = {
      uid: function (obj) {
        return obj ? obj[uidMagic] || (obj[uidMagic] = ++uidCount) : ++uidCount
      }, hook: function (fn, callback) {
        var dg;
        if (fn && fn._callbacks) {
          dg = fn
        } else {
          dg = function () {
            var q;
            if (fn) {
              q = fn.apply(this, arguments)
            }
            var callbacks = dg._callbacks;
            var k = callbacks.length;
            while (k--) {
              var r = callbacks[k].apply(this, arguments);
              if (q === undefined) {
                q = r
              }
            }
            return q
          };
          dg._callbacks = []
        }
        dg._callbacks.push(callback);
        return dg
      }, createElementByHtml: function (html) {
        var el = document.createElement("div");
        el.innerHTML = html;
        el = el.firstChild;
        el.parentNode.removeChild(el);
        return el
      }, getViewportElement: function () {
        return browser.ie && browser.quirks ? document.body : document.documentElement
      }, getClientRect: function (element) {
        var bcr;
        try {
          bcr = element.getBoundingClientRect()
        } catch (e) {
          bcr = {left: 0, top: 0, height: 0, width: 0}
        }
        var rect = {left: Math.round(bcr.left), top: Math.round(bcr.top), height: Math.round(bcr.bottom - bcr.top), width: Math.round(bcr.right - bcr.left)};
        var doc;
        while ((doc = element.ownerDocument) !== document && (element = domUtils.getWindow(doc).frameElement)) {
          bcr = element.getBoundingClientRect();
          rect.left += bcr.left;
          rect.top += bcr.top
        }
        rect.bottom = rect.top + rect.height;
        rect.right = rect.left + rect.width;
        return rect
      }, getViewportRect: function () {
        var viewportEl = uiUtils.getViewportElement();
        var width = (window.innerWidth || viewportEl.clientWidth) | 0;
        var height = (window.innerHeight || viewportEl.clientHeight) | 0;
        return {left: 0, top: 0, height: height, width: width, bottom: height, right: width}
      }, setViewportOffset: function (element, offset) {
        var rect;
        var fixedLayer = uiUtils.getFixedLayer();
        if (element.parentNode === fixedLayer) {
          element.style.left = offset.left + "px";
          element.style.top = offset.top + "px"
        } else {
          domUtils.setViewportOffset(element, offset)
        }
      }, getEventOffset: function (evt) {
        var el = evt.target || evt.srcElement;
        var rect = uiUtils.getClientRect(el);
        var offset = uiUtils.getViewportOffsetByEvent(evt);
        return {left: offset.left - rect.left, top: offset.top - rect.top}
      }, getViewportOffsetByEvent: function (evt) {
        var el = evt.target || evt.srcElement;
        var frameEl = domUtils.getWindow(el).frameElement;
        var offset = {left: evt.clientX, top: evt.clientY};
        if (frameEl && el.ownerDocument !== document) {
          var rect = uiUtils.getClientRect(frameEl);
          offset.left += rect.left;
          offset.top += rect.top
        }
        return offset
      }, setGlobal: function (id, obj) {
        root[id] = obj;
        return magic + '["' + id + '"]'
      }, unsetGlobal: function (id) {
        delete root[id]
      }, copyAttributes: function (tgt, src) {
        var attributes = src.attributes;
        var k = attributes.length;
        while (k--) {
          var attrNode = attributes[k];
          if (attrNode.nodeName != "style" && attrNode.nodeName != "class" && (!browser.ie || attrNode.specified)) {
            tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue)
          }
        }
        if (src.className) {
          domUtils.addClass(tgt, src.className)
        }
        if (src.style.cssText) {
          tgt.style.cssText += ";" + src.style.cssText
        }
      }, removeStyle: function (el, styleName) {
        if (el.style.removeProperty) {
          el.style.removeProperty(styleName)
        } else if (el.style.removeAttribute) {
          el.style.removeAttribute(styleName)
        } else throw""
      }, contains: function (elA, elB) {
        return elA && elB && (elA === elB ? false : elA.contains ? elA.contains(elB) : elA.compareDocumentPosition(elB) & 16)
      }, startDrag: function (evt, callbacks, doc) {
        var doc = doc || document;
        var startX = evt.clientX;
        var startY = evt.clientY;

        function handleMouseMove(evt) {
          var x = evt.clientX - startX;
          var y = evt.clientY - startY;
          callbacks.ondragmove(x, y, evt);
          if (evt.stopPropagation) {
            evt.stopPropagation()
          } else {
            evt.cancelBubble = true
          }
        }

        if (doc.addEventListener) {
          function handleMouseUp(evt) {
            doc.removeEventListener("mousemove", handleMouseMove, true);
            doc.removeEventListener("mouseup", handleMouseUp, true);
            window.removeEventListener("mouseup", handleMouseUp, true);
            callbacks.ondragstop()
          }

          doc.addEventListener("mousemove", handleMouseMove, true);
          doc.addEventListener("mouseup", handleMouseUp, true);
          window.addEventListener("mouseup", handleMouseUp, true);
          evt.preventDefault()
        } else {
          var elm = evt.srcElement;
          elm.setCapture();

          function releaseCaptrue() {
            elm.releaseCapture();
            elm.detachEvent("onmousemove", handleMouseMove);
            elm.detachEvent("onmouseup", releaseCaptrue);
            elm.detachEvent("onlosecaptrue", releaseCaptrue);
            callbacks.ondragstop()
          }

          elm.attachEvent("onmousemove", handleMouseMove);
          elm.attachEvent("onmouseup", releaseCaptrue);
          elm.attachEvent("onlosecaptrue", releaseCaptrue);
          evt.returnValue = false
        }
        callbacks.ondragstart()
      }, getFixedLayer: function () {
        var layer = document.getElementById("edui_fixedlayer");
        if (layer == null) {
          layer = document.createElement("div");
          layer.id = "edui_fixedlayer";
          document.body.appendChild(layer);
          if (browser.ie && browser.version <= 8) {
            layer.style.position = "absolute";
            bindFixedLayer();
            setTimeout(updateFixedOffset)
          } else {
            layer.style.position = "fixed"
          }
          layer.style.left = "0";
          layer.style.top = "0";
          layer.style.width = "0";
          layer.style.height = "0";
          layer.style.margin = "0"
        }
        return layer
      }, makeUnselectable: function (element) {
        if (browser.opera || browser.ie && browser.version < 9) {
          element.unselectable = "on";
          if (element.hasChildNodes()) {
            for (var i = 0; i < element.childNodes.length; i++) {
              if (element.childNodes[i].nodeType === 1) {
                uiUtils.makeUnselectable(element.childNodes[i])
              }
            }
          }
        } else {
          if (element.style.MozUserSelect !== undefined) {
            element.style.MozUserSelect = "none"
          } else if (element.style.WebkitUserSelect !== undefined) {
            element.style.WebkitUserSelect = "none"
          } else if (element.style.KhtmlUserSelect !== undefined) {
            element.style.KhtmlUserSelect = "none"
          }
        }
      }
    };

    function updateFixedOffset() {
      var layer = document.getElementById("edui_fixedlayer");
      uiUtils.setViewportOffset(layer, {left: 0, top: 0})
    }

    function bindFixedLayer(adjOffset) {
      domUtils.on(window, "scroll", updateFixedOffset);
      domUtils.on(window, "resize", baidu.editor.utils.defer(updateFixedOffset, 0, true))
    }
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, EventBase = baidu.editor.EventBase, UIBase = baidu.editor.ui.UIBase = function () {
    };
    UIBase.prototype = {
      el: null, className: "", uiName: "", initOptions: function (options) {
        var me = this;
        for (var k in options) {
          me[k] = options[k]
        }
        this.id = this.id || "edui" + uiUtils.uid()
      }, initUIBase: function () {
        this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this))
      }, render: function (holder) {
        var html = this.renderHtml();
        var el = uiUtils.createElementByHtml(html);
        var list = domUtils.getElementsByTagName(el, "*");
        var theme = "edui-" + (this.theme || this.editor.options.theme);
        var layer = document.getElementById("edui_fixedlayer");
        for (var i = 0, node; node = list[i++];) {
          domUtils.addClass(node, theme)
        }
        domUtils.addClass(el, theme);
        if (layer) {
          layer.className = "";
          domUtils.addClass(layer, theme)
        }
        var seatEl = this.getDom();
        if (seatEl != null) {
          seatEl.parentNode.replaceChild(el, seatEl);
          uiUtils.copyAttributes(el, seatEl)
        } else {
          if (typeof holder == "string") {
            holder = document.getElementById(holder)
          }
          holder = holder || uiUtils.getFixedLayer();
          domUtils.addClass(holder, theme);
          holder.appendChild(el)
        }
        this.el = el;
        this.postRender()
      }, getDom: function (name) {
        if (!name) {
          return document.getElementById(this.id)
        } else {
          return document.getElementById(this.id + "_" + name)
        }
      }, postRender: function () {
        this.fireEvent("postrender")
      }, getHtmlTpl: function () {
        return ""
      }, formatHtml: function (tpl) {
        var prefix = "edui-" + this.uiName;
        return tpl.replace(/##/g, this.id).replace(/%%-/g, this.uiName ? prefix + "-" : "").replace(/%%/g, (this.uiName ? prefix : "") + " " + this.className).replace(/\$\$/g, this._globalKey)
      }, renderHtml: function () {
        return this.formatHtml(this.getHtmlTpl())
      }, dispose: function () {
        var box = this.getDom();
        if (box) baidu.editor.dom.domUtils.remove(box);
        uiUtils.unsetGlobal(this.id)
      }, uiIsShow: true, uiShowStyleBackupValue: null, uiShow: function (enable) {
        if (enable) {
          if (this.uiIsShow) {
            return
          }
          this.getDom().style.display = this.uiShowStyleBackupValue;
          this.uiIsShow = true
        } else {
          if (!this.uiIsShow) {
            return
          }
          this.uiShowStyleBackupValue = this.getDom().style.display;
          this.getDom().style.display = "none";
          this.uiIsShow = false
        }
      }
    };
    utils.inherits(UIBase, EventBase)
  })();
  (function () {
    var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Separator = baidu.editor.ui.Separator = function (options) {
      this.initOptions(options);
      this.initSeparator()
    };
    Separator.prototype = {
      uiName: "separator", initSeparator: function () {
        this.initUIBase()
      }, getHtmlTpl: function () {
        return '<div id="##" class="edui-box %%"></div>'
      }
    };
    utils.inherits(Separator, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, uiUtils = baidu.editor.ui.uiUtils;
    var Mask = baidu.editor.ui.Mask = function (options) {
      this.initOptions(options);
      this.initUIBase()
    };
    Mask.prototype = {
      getHtmlTpl: function () {
        return '<div id="##" class="edui-mask %%" onclick="return $$._onClick(event, this);" onmousedown="return $$._onMouseDown(event, this);"></div>'
      }, postRender: function () {
        var me = this;
        domUtils.on(window, "resize", function () {
          setTimeout(function () {
            if (!me.isHidden()) {
              me._fill()
            }
          })
        })
      }, show: function (zIndex) {
        this._fill();
        this.getDom().style.display = "";
        this.getDom().style.zIndex = zIndex
      }, hide: function () {
        this.getDom().style.display = "none";
        this.getDom().style.zIndex = ""
      }, isHidden: function () {
        return this.getDom().style.display == "none"
      }, _onMouseDown: function () {
        return false
      }, _onClick: function (e, target) {
        this.fireEvent("click", e, target)
      }, _fill: function () {
        var el = this.getDom();
        var vpRect = uiUtils.getViewportRect();
        el.style.width = vpRect.width + "px";
        el.style.height = vpRect.height + "px"
      }
    };
    utils.inherits(Mask, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Popup = baidu.editor.ui.Popup = function (options) {
      this.initOptions(options);
      this.initPopup()
    };
    var allPopups = [];

    function closeAllPopup(evt, el) {
      for (var i = 0; i < allPopups.length; i++) {
        var pop = allPopups[i];
        if (!pop.isHidden()) {
          if (pop.queryAutoHide(el) !== false) {
            if (evt && /scroll/gi.test(evt.type) && pop.className === "edui-wordpastepop") return;
            pop.hide()
          }
        }
      }
      if (allPopups.length) pop.editor.fireEvent("afterhidepop")
    }

    Popup.postHide = closeAllPopup;
    var ANCHOR_CLASSES = ["edui-anchor-topleft", "edui-anchor-topright", "edui-anchor-bottomleft", "edui-anchor-bottomright"];
    Popup.prototype = {
      SHADOW_RADIUS: 5, content: null, _hidden: false, autoRender: true, canSideLeft: true, canSideUp: true, initPopup: function () {
        this.initUIBase();
        allPopups.push(this)
      }, getHtmlTpl: function () {
        return '<div id="##" class="edui-popup %%" onmousedown="return false;">' + ' <div id="##_body" class="edui-popup-body">' + ' <iframe style="position:absolute;z-index:-1;left:0;top:0;background-color: transparent;" frameborder="0" width="100%" height="100%" src="about:blank"></iframe>' + ' <div class="edui-shadow"></div>' + ' <div id="##_content" class="edui-popup-content">' + this.getContentHtmlTpl() + "  </div>" + " </div>" + "</div>"
      }, getContentHtmlTpl: function () {
        if (this.content) {
          if (typeof this.content == "string") {
            return this.content
          }
          return this.content.renderHtml()
        } else {
          return ""
        }
      }, _UIBase_postRender: UIBase.prototype.postRender, postRender: function () {
        if (this.content instanceof UIBase) {
          this.content.postRender()
        }
        if (this.captureWheel && !this.captured) {
          this.captured = true;
          var winHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 80, _height = this.getDom().offsetHeight, _top = uiUtils.getClientRect(this.combox.getDom()).top, content = this.getDom("content"),
            ifr = this.getDom("body").getElementsByTagName("iframe"), me = this;
          ifr.length && (ifr = ifr[0]);
          while (_top + _height > winHeight) {
            _height -= 30
          }
          content.style.height = _height + "px";
          ifr && (ifr.style.height = _height + "px");
          domUtils.on(content, "onmousewheel" in document.body ? "mousewheel" : "DOMMouseScroll", function (e) {
            if (e.preventDefault) {
              e.preventDefault()
            } else {
              e.returnValue = false
            }
            if (e.wheelDelta) {
              content.scrollTop -= e.wheelDelta / 120 * 60
            } else {
              content.scrollTop -= e.detail / -3 * 60
            }
          })
        }
        this.fireEvent("postRenderAfter");
        this.hide(true);
        this._UIBase_postRender()
      }, _doAutoRender: function () {
        if (!this.getDom() && this.autoRender) {
          this.render()
        }
      }, mesureSize: function () {
        var box = this.getDom("content");
        return uiUtils.getClientRect(box)
      }, fitSize: function () {
        if (this.captureWheel && this.sized) {
          return this.__size
        }
        this.sized = true;
        var popBodyEl = this.getDom("body");
        popBodyEl.style.width = "";
        popBodyEl.style.height = "";
        var size = this.mesureSize();
        if (this.captureWheel) {
          popBodyEl.style.width = -(-20 - size.width) + "px";
          var height = parseInt(this.getDom("content").style.height, 10);
          !window.isNaN(height) && (size.height = height)
        } else {
          popBodyEl.style.width = size.width + "px"
        }
        popBodyEl.style.height = size.height + "px";
        this.__size = size;
        this.captureWheel && (this.getDom("content").style.overflow = "auto");
        return size
      }, showAnchor: function (element, hoz) {
        this.showAnchorRect(uiUtils.getClientRect(element), hoz)
      }, showAnchorRect: function (rect, hoz, adj) {
        this._doAutoRender();
        var vpRect = uiUtils.getViewportRect();
        this.getDom().style.visibility = "hidden";
        this._show();
        var popSize = this.fitSize();
        var sideLeft, sideUp, left, top;
        if (hoz) {
          sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);
          sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);
          left = sideLeft ? rect.left - popSize.width : rect.right;
          top = sideUp ? rect.bottom - popSize.height : rect.top
        } else {
          sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);
          sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);
          left = sideLeft ? rect.right - popSize.width : rect.left;
          top = sideUp ? rect.top - popSize.height : rect.bottom
        }
        if (!sideUp) {
          if (top + popSize.height > vpRect.bottom) {
            top = vpRect.bottom - popSize.height
          }
        }
        var popEl = this.getDom();
        uiUtils.setViewportOffset(popEl, {left: left, top: top});
        domUtils.removeClasses(popEl, ANCHOR_CLASSES);
        popEl.className += " " + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)];
        if (this.editor) {
          popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10;
          baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1
        }
        this.getDom().style.visibility = "visible"
      }, showAt: function (offset) {
        var left = offset.left;
        var top = offset.top;
        var rect = {left: left, top: top, right: left, bottom: top, height: 0, width: 0};
        this.showAnchorRect(rect, false, true)
      }, _show: function () {
        if (this._hidden) {
          var box = this.getDom();
          box.style.display = "";
          this._hidden = false;
          this.fireEvent("show")
        }
      }, isHidden: function () {
        return this._hidden
      }, show: function () {
        this._doAutoRender();
        this._show()
      }, hide: function (notNofity) {
        if (!this._hidden && this.getDom()) {
          this.getDom().style.display = "none";
          this._hidden = true;
          if (!notNofity) {
            this.fireEvent("hide")
          }
        }
      }, queryAutoHide: function (el) {
        return !el || !uiUtils.contains(this.getDom(), el)
      }
    };
    utils.inherits(Popup, UIBase);
    domUtils.on(document, "mousedown", function (evt) {
      var el = evt.target || evt.srcElement;
      closeAllPopup(evt, el)
    });
    domUtils.on(window, "scroll", function (evt, el) {
      closeAllPopup(evt, el)
    })
  })();
  (function () {
    var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, ColorPicker = baidu.editor.ui.ColorPicker = function (options) {
      this.initOptions(options);
      this.noColorText = this.noColorText || this.editor.getLang("clearColor");
      this.initUIBase()
    };
    ColorPicker.prototype = {
      getHtmlTpl: function () {
        return genColorPicker(this.noColorText, this.editor)
      }, _onTableClick: function (evt) {
        var tgt = evt.target || evt.srcElement;
        var color = tgt.getAttribute("data-color");
        if (color) {
          this.fireEvent("pickcolor", color)
        }
      }, _onTableOver: function (evt) {
        var tgt = evt.target || evt.srcElement;
        var color = tgt.getAttribute("data-color");
        if (color) {
          this.getDom("preview").style.backgroundColor = color
        }
      }, _onTableOut: function () {
        this.getDom("preview").style.backgroundColor = ""
      }, _onPickNoColor: function () {
        this.fireEvent("picknocolor")
      }, _onColorSelect: function (evt) {
        var input = evt.target || evt.srcElement;
        var color = input.value;
        if (color) {
          this.fireEvent("pickcolor", color)
        }
      }
    };
    utils.inherits(ColorPicker, UIBase);
    var COLORS = ("ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646," + "f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada," + "d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5," + "bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f," + "a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09," + "7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806," + "c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,").split(",");

    function genColorPicker(noColorText, editor) {
      var html = '<div id="##" class="edui-colorpicker %%">' + '<div class="edui-colorpicker-topbar edui-clearfix">' + '<div id="##_preview" class="edui-colorpicker-preview"><input type="color" id="##_input" onchange="$$._onColorSelect(event,this);" /></div>' + '<div unselectable="on" class="edui-colorpicker-nocolor" onclick="$$._onPickNoColor(event, this);">' + noColorText + "</div>" + "</div>" + '<table  class="edui-box" style="border-collapse: collapse;" onmouseover="$$._onTableOver(event, this);" onmouseout="$$._onTableOut(event, this);" onclick="return $$._onTableClick(event, this);" cellspacing="0" cellpadding="0">' + '<tr style="border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;padding-top: 2px"><td colspan="10">' + editor.getLang("themeColor") + "</td> </tr>" + '<tr class="edui-colorpicker-tablefirstrow" >';
      for (var i = 0; i < COLORS.length; i++) {
        if (i && i % 10 === 0) {
          html += "</tr>" + (i == 60 ? '<tr style="border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;"><td colspan="10">' + editor.getLang("standardColor") + "</td></tr>" : "") + "<tr" + (i == 60 ? ' class="edui-colorpicker-tablefirstrow"' : "") + ">"
        }
        html += i < 70 ? '<td style="padding:2px 2px;"><a hidefocus title="' + COLORS[i] + '" onclick="return false;" href="javascript:" unselectable="on" class="edui-box edui-colorpicker-colorcell"' + ' data-color="#' + COLORS[i] + '"' + ' style="background-color:#' + COLORS[i] + ";border:solid #ccc 1px;" + '"' + "></a></td>" : ""
      }
      html += "</tr>";
      html += "</table></div>";
      return html
    }
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase;
    var TablePicker = baidu.editor.ui.TablePicker = function (options) {
      this.initOptions(options);
      this.initTablePicker()
    };
    TablePicker.prototype = {
      defaultNumRows: 10, defaultNumCols: 10, maxNumRows: 20, maxNumCols: 20, numRows: 10, numCols: 10, lengthOfCellSide: 22, initTablePicker: function () {
        this.initUIBase()
      }, getHtmlTpl: function () {
        var me = this;
        return '<div id="##" class="edui-tablepicker %%">' + '<div class="edui-tablepicker-body">' + '<div class="edui-infoarea">' + '<span id="##_label" class="edui-label"></span>' + "</div>" + '<div class="edui-pickarea"' + ' onmousemove="$$._onMouseMove(event, this);"' + ' onmouseover="$$._onMouseOver(event, this);"' + ' onmouseout="$$._onMouseOut(event, this);"' + ' onclick="$$._onClick(event, this);"' + ">" + '<div id="##_overlay" class="edui-overlay"></div>' + "</div>" + "</div>" + "</div>"
      }, _UIBase_render: UIBase.prototype.render, render: function (holder) {
        this._UIBase_render(holder);
        this.getDom("label").innerHTML = "0" + this.editor.getLang("t_row") + " x 0" + this.editor.getLang("t_col")
      }, _track: function (numCols, numRows) {
        var style = this.getDom("overlay").style;
        var sideLen = this.lengthOfCellSide;
        style.width = numCols * sideLen + "px";
        style.height = numRows * sideLen + "px";
        var label = this.getDom("label");
        label.innerHTML = numCols + this.editor.getLang("t_col") + " x " + numRows + this.editor.getLang("t_row");
        this.numCols = numCols;
        this.numRows = numRows
      }, _onMouseOver: function (evt, el) {
        var rel = evt.relatedTarget || evt.fromElement;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.getDom("label").innerHTML = "0" + this.editor.getLang("t_col") + " x 0" + this.editor.getLang("t_row");
          this.getDom("overlay").style.visibility = ""
        }
      }, _onMouseOut: function (evt, el) {
        var rel = evt.relatedTarget || evt.toElement;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.getDom("label").innerHTML = "0" + this.editor.getLang("t_col") + " x 0" + this.editor.getLang("t_row");
          this.getDom("overlay").style.visibility = "hidden"
        }
      }, _onMouseMove: function (evt, el) {
        var style = this.getDom("overlay").style;
        var offset = uiUtils.getEventOffset(evt);
        var sideLen = this.lengthOfCellSide;
        var numCols = Math.ceil(offset.left / sideLen);
        var numRows = Math.ceil(offset.top / sideLen);
        this._track(numCols, numRows)
      }, _onClick: function () {
        this.fireEvent("picktable", this.numCols, this.numRows)
      }
    };
    utils.inherits(TablePicker, UIBase)
  })();
  (function () {
    var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils;
    var TPL_STATEFUL = 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + (browser.ie ? ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"' : ' onmouseover="$$.Stateful_onMouseOver(event, this);"' + ' onmouseout="$$.Stateful_onMouseOut(event, this);"');
    baidu.editor.ui.Stateful = {
      alwalysHoverable: false, target: null, Stateful_init: function () {
        this._Stateful_dGetHtmlTpl = this.getHtmlTpl;
        this.getHtmlTpl = this.Stateful_getHtmlTpl
      }, Stateful_getHtmlTpl: function () {
        var tpl = this._Stateful_dGetHtmlTpl();
        return tpl.replace(/stateful/g, function () {
          return TPL_STATEFUL
        })
      }, Stateful_onMouseEnter: function (evt, el) {
        this.target = el;
        if (!this.isDisabled() || this.alwalysHoverable) {
          this.addState("hover");
          this.fireEvent("over")
        }
      }, Stateful_onMouseLeave: function (evt, el) {
        if (!this.isDisabled() || this.alwalysHoverable) {
          this.removeState("hover");
          this.removeState("active");
          this.fireEvent("out")
        }
      }, Stateful_onMouseOver: function (evt, el) {
        var rel = evt.relatedTarget;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.Stateful_onMouseEnter(evt, el)
        }
      }, Stateful_onMouseOut: function (evt, el) {
        var rel = evt.relatedTarget;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.Stateful_onMouseLeave(evt, el)
        }
      }, Stateful_onMouseDown: function (evt, el) {
        if (!this.isDisabled()) {
          this.addState("active")
        }
      }, Stateful_onMouseUp: function (evt, el) {
        if (!this.isDisabled()) {
          this.removeState("active")
        }
      }, Stateful_postRender: function () {
        if (this.disabled && !this.hasState("disabled")) {
          this.addState("disabled")
        }
      }, hasState: function (state) {
        return domUtils.hasClass(this.getStateDom(), "edui-state-" + state)
      }, addState: function (state) {
        if (!this.hasState(state)) {
          this.getStateDom().className += " edui-state-" + state
        }
      }, removeState: function (state) {
        if (this.hasState(state)) {
          domUtils.removeClasses(this.getStateDom(), ["edui-state-" + state])
        }
      }, getStateDom: function () {
        return this.getDom("state")
      }, isChecked: function () {
        return this.hasState("checked")
      }, setChecked: function (checked) {
        if (!this.isDisabled() && checked) {
          this.addState("checked")
        } else {
          this.removeState("checked")
        }
      }, isDisabled: function () {
        return this.hasState("disabled")
      }, setDisabled: function (disabled) {
        if (disabled) {
          this.removeState("hover");
          this.removeState("checked");
          this.removeState("active");
          this.addState("disabled")
        } else {
          this.removeState("disabled")
        }
      }
    }
  })();
  (function () {
    var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Stateful = baidu.editor.ui.Stateful, Button = baidu.editor.ui.Button = function (options) {
      if (options.name) {
        var btnName = options.name;
        var cssRules = options.cssRules;
        if (!options.className) {
          options.className = "edui-for-" + btnName
        }
        options.cssRules = ".edui-" + (options.theme || "default") + " .edui-toolbar .edui-button.edui-for-" + btnName + " .edui-icon {" + cssRules + "}"
      }
      this.initOptions(options);
      this.initButton()
    };
    Button.prototype = {
      uiName: "button", label: "", title: "", showIcon: true, showText: true, cssRules: "", initButton: function () {
        this.initUIBase();
        this.Stateful_init();
        if (this.cssRules) {
          utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules)
        }
      }, getHtmlTpl: function () {
        return '<div id="##" class="edui-box %%">' + '<div id="##_state" stateful>' + '<div class="%%-wrap"><div id="##_body" unselectable="on" ' + (this.title ? 'title="' + this.title + '"' : "") + ' class="%%-body" onmousedown="return $$._onMouseDown(event, this);" onclick="return $$._onClick(event, this);">' + (this.showIcon ? '<div class="edui-box edui-icon"></div>' : "") + (this.showText ? '<div class="edui-box edui-label">' + this.label + "</div>" : "") + "</div>" + "</div>" + "</div></div>"
      }, postRender: function () {
        this.Stateful_postRender();
        this.setDisabled(this.disabled)
      }, _onMouseDown: function (e) {
        var target = e.target || e.srcElement, tagName = target && target.tagName && target.tagName.toLowerCase();
        if (tagName == "input" || tagName == "object" || tagName == "object") {
          return false
        }
      }, _onClick: function () {
        if (!this.isDisabled()) {
          this.fireEvent("click")
        }
      }, setTitle: function (text) {
        var label = this.getDom("label");
        label.innerHTML = text
      }
    };
    utils.inherits(Button, UIBase);
    utils.extend(Button.prototype, Stateful)
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Stateful = baidu.editor.ui.Stateful, SplitButton = baidu.editor.ui.SplitButton = function (options) {
      this.initOptions(options);
      this.initSplitButton()
    };
    SplitButton.prototype = {
      popup: null, uiName: "splitbutton", title: "", initSplitButton: function () {
        this.initUIBase();
        this.Stateful_init();
        var me = this;
        if (this.popup != null) {
          var popup = this.popup;
          this.popup = null;
          this.setPopup(popup)
        }
      }, _UIBase_postRender: UIBase.prototype.postRender, postRender: function () {
        this.Stateful_postRender();
        this._UIBase_postRender()
      }, setPopup: function (popup) {
        if (this.popup === popup) return;
        if (this.popup != null) {
          this.popup.dispose()
        }
        popup.addListener("show", utils.bind(this._onPopupShow, this));
        popup.addListener("hide", utils.bind(this._onPopupHide, this));
        popup.addListener("postrender", utils.bind(function () {
          popup.getDom("body").appendChild(uiUtils.createElementByHtml('<div id="' + this.popup.id + '_bordereraser" class="edui-bordereraser edui-background" style="width:' + (uiUtils.getClientRect(this.getDom()).width + 20) + 'px"></div>'));
          popup.getDom().className += " " + this.className
        }, this));
        this.popup = popup
      }, _onPopupShow: function () {
        this.addState("opened")
      }, _onPopupHide: function () {
        this.removeState("opened")
      }, getHtmlTpl: function () {
        return '<div id="##" class="edui-box %%">' + "<div " + (this.title ? 'title="' + this.title + '"' : "") + ' id="##_state" stateful><div class="%%-body">' + '<div id="##_button_body" class="edui-box edui-button-body" onclick="$$._onButtonClick(event, this);">' + '<div class="edui-box edui-icon"></div>' + "</div>" + '<div class="edui-box edui-splitborder"></div>' + '<div class="edui-box edui-arrow" onclick="$$._onArrowClick();"></div>' + "</div></div></div>"
      }, showPopup: function () {
        var rect = uiUtils.getClientRect(this.getDom());
        rect.top -= this.popup.SHADOW_RADIUS;
        rect.height += this.popup.SHADOW_RADIUS;
        this.popup.showAnchorRect(rect)
      }, _onArrowClick: function (event, el) {
        if (!this.isDisabled()) {
          this.showPopup()
        }
      }, _onButtonClick: function () {
        if (!this.isDisabled()) {
          this.fireEvent("buttonclick")
        }
      }
    };
    utils.inherits(SplitButton, UIBase);
    utils.extend(SplitButton.prototype, Stateful, true)
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, ColorPicker = baidu.editor.ui.ColorPicker, Popup = baidu.editor.ui.Popup, SplitButton = baidu.editor.ui.SplitButton,
      ColorButton = baidu.editor.ui.ColorButton = function (options) {
        this.initOptions(options);
        this.initColorButton()
      };
    ColorButton.prototype = {
      initColorButton: function () {
        var me = this;
        this.popup = new Popup({
          content: new ColorPicker({
            noColorText: me.editor.getLang("clearColor"), editor: me.editor, onpickcolor: function (t, color) {
              me._onPickColor(color)
            }, onpicknocolor: function (t, color) {
              me._onPickNoColor(color)
            }
          }), editor: me.editor
        });
        this.initSplitButton()
      }, _SplitButton_postRender: SplitButton.prototype.postRender, postRender: function () {
        this._SplitButton_postRender();
        this.getDom("button_body").appendChild(uiUtils.createElementByHtml('<div id="' + this.id + '_colorlump" class="edui-colorlump"></div>'));
        this.getDom().className += " edui-colorbutton"
      }, setColor: function (color) {
        this.getDom("colorlump").style.backgroundColor = color;
        this.color = color
      }, _onPickColor: function (color) {
        if (this.fireEvent("pickcolor", color) !== false) {
          this.setColor(color);
          this.popup.hide()
        }
      }, _onPickNoColor: function (color) {
        if (this.fireEvent("picknocolor") !== false) {
          this.popup.hide()
        }
      }
    };
    utils.inherits(ColorButton, SplitButton)
  })();
  (function () {
    var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, TablePicker = baidu.editor.ui.TablePicker, SplitButton = baidu.editor.ui.SplitButton, TableButton = baidu.editor.ui.TableButton = function (options) {
      this.initOptions(options);
      this.initTableButton()
    };
    TableButton.prototype = {
      initTableButton: function () {
        var me = this;
        this.popup = new Popup({
          content: new TablePicker({
            editor: me.editor, onpicktable: function (t, numCols, numRows) {
              me._onPickTable(numCols, numRows)
            }
          }), editor: me.editor
        });
        this.initSplitButton()
      }, _onPickTable: function (numCols, numRows) {
        if (this.fireEvent("picktable", numCols, numRows) !== false) {
          this.popup.hide()
        }
      }
    };
    utils.inherits(TableButton, SplitButton)
  })();
  (function () {
    var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase;
    var AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker = function (options) {
      this.initOptions(options);
      this.initAutoTypeSetPicker()
    };
    AutoTypeSetPicker.prototype = {
      initAutoTypeSetPicker: function () {
        this.initUIBase()
      }, getHtmlTpl: function () {
        var me = this.editor, opt = me.options.autotypeset, lang = me.getLang("autoTypeSet");
        var textAlignInputName = "textAlignValue" + me.uid, imageBlockInputName = "imageBlockLineValue" + me.uid, symbolConverInputName = "symbolConverValue" + me.uid;
        return '<div id="##" class="edui-autotypesetpicker %%">' + '<div class="edui-autotypesetpicker-body">' + "<table >" + '<tr><td nowrap><input type="checkbox" name="mergeEmptyline" ' + (opt["mergeEmptyline"] ? "checked" : "") + ">" + lang.mergeLine + '</td><td colspan="2"><input type="checkbox" name="removeEmptyline" ' + (opt["removeEmptyline"] ? "checked" : "") + ">" + lang.delLine + "</td></tr>" + '<tr><td nowrap><input type="checkbox" name="removeClass" ' + (opt["removeClass"] ? "checked" : "") + ">" + lang.removeFormat + '</td><td colspan="2"><input type="checkbox" name="indent" ' + (opt["indent"] ? "checked" : "") + ">" + lang.indent + "</td></tr>" + "<tr>" + '<td nowrap><input type="checkbox" name="textAlign" ' + (opt["textAlign"] ? "checked" : "") + ">" + lang.alignment + "</td>" + '<td colspan="2" id="' + textAlignInputName + '">' + '<input type="radio" name="' + textAlignInputName + '" value="left" ' + (opt["textAlign"] && opt["textAlign"] == "left" ? "checked" : "") + ">" + me.getLang("justifyleft") + '<input type="radio" name="' + textAlignInputName + '" value="center" ' + (opt["textAlign"] && opt["textAlign"] == "center" ? "checked" : "") + ">" + me.getLang("justifycenter") + '<input type="radio" name="' + textAlignInputName + '" value="right" ' + (opt["textAlign"] && opt["textAlign"] == "right" ? "checked" : "") + ">" + me.getLang("justifyright") + "</td>" + "</tr>" + "<tr>" + '<td nowrap><input type="checkbox" name="imageBlockLine" ' + (opt["imageBlockLine"] ? "checked" : "") + ">" + lang.imageFloat + "</td>" + '<td nowrap id="' + imageBlockInputName + '">' + '<input type="radio" name="' + imageBlockInputName + '" value="none" ' + (opt["imageBlockLine"] && opt["imageBlockLine"] == "none" ? "checked" : "") + ">" + me.getLang("default") + '<input type="radio" name="' + imageBlockInputName + '" value="left" ' + (opt["imageBlockLine"] && opt["imageBlockLine"] == "left" ? "checked" : "") + ">" + me.getLang("justifyleft") + '<input type="radio" name="' + imageBlockInputName + '" value="center" ' + (opt["imageBlockLine"] && opt["imageBlockLine"] == "center" ? "checked" : "") + ">" + me.getLang("justifycenter") + '<input type="radio" name="' + imageBlockInputName + '" value="right" ' + (opt["imageBlockLine"] && opt["imageBlockLine"] == "right" ? "checked" : "") + ">" + me.getLang("justifyright") + "</td>" + "</tr>" + '<tr><td nowrap><input type="checkbox" name="clearFontSize" ' + (opt["clearFontSize"] ? "checked" : "") + ">" + lang.removeFontsize + '</td><td colspan="2"><input type="checkbox" name="clearFontFamily" ' + (opt["clearFontFamily"] ? "checked" : "") + ">" + lang.removeFontFamily + "</td></tr>" + '<tr><td nowrap colspan="3"><input type="checkbox" name="removeEmptyNode" ' + (opt["removeEmptyNode"] ? "checked" : "") + ">" + lang.removeHtml + "</td></tr>" + '<tr><td nowrap colspan="3"><input type="checkbox" name="pasteFilter" ' + (opt["pasteFilter"] ? "checked" : "") + ">" + lang.pasteFilter + "</td></tr>" + "<tr>" + '<td nowrap><input type="checkbox" name="symbolConver" ' + (opt["bdc2sb"] || opt["tobdc"] ? "checked" : "") + ">" + lang.symbol + "</td>" + '<td id="' + symbolConverInputName + '">' + '<input type="radio" name="bdc" value="bdc2sb" ' + (opt["bdc2sb"] ? "checked" : "") + ">" + lang.bdc2sb + '<input type="radio" name="bdc" value="tobdc" ' + (opt["tobdc"] ? "checked" : "") + ">" + lang.tobdc + "" + "</td>" + '<td nowrap align="right"><button >' + lang.run + "</button></td>" + "</tr>" + "</table>" + "</div>" + "</div>"
      }, _UIBase_render: UIBase.prototype.render
    };
    utils.inherits(AutoTypeSetPicker, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, SplitButton = baidu.editor.ui.SplitButton, AutoTypeSetButton = baidu.editor.ui.AutoTypeSetButton = function (options) {
      this.initOptions(options);
      this.initAutoTypeSetButton()
    };

    function getPara(me) {
      var opt = {}, cont = me.getDom(), editorId = me.editor.uid, inputType = null, attrName = null, ipts = domUtils.getElementsByTagName(cont, "input");
      for (var i = ipts.length - 1, ipt; ipt = ipts[i--];) {
        inputType = ipt.getAttribute("type");
        if (inputType == "checkbox") {
          attrName = ipt.getAttribute("name");
          opt[attrName] && delete opt[attrName];
          if (ipt.checked) {
            var attrValue = document.getElementById(attrName + "Value" + editorId);
            if (attrValue) {
              if (/input/gi.test(attrValue.tagName)) {
                opt[attrName] = attrValue.value
              } else {
                var iptChilds = attrValue.getElementsByTagName("input");
                for (var j = iptChilds.length - 1, iptchild; iptchild = iptChilds[j--];) {
                  if (iptchild.checked) {
                    opt[attrName] = iptchild.value;
                    break
                  }
                }
              }
            } else {
              opt[attrName] = true
            }
          } else {
            opt[attrName] = false
          }
        } else {
          opt[ipt.getAttribute("value")] = ipt.checked
        }
      }
      var selects = domUtils.getElementsByTagName(cont, "select");
      for (var i = 0, si; si = selects[i++];) {
        var attr = si.getAttribute("name");
        opt[attr] = opt[attr] ? si.value : ""
      }
      utils.extend(me.editor.options.autotypeset, opt);
      me.editor.setPreferences("autotypeset", opt)
    }

    AutoTypeSetButton.prototype = {
      initAutoTypeSetButton: function () {
        var me = this;
        this.popup = new Popup({
          content: new AutoTypeSetPicker({editor: me.editor}), editor: me.editor, hide: function () {
            if (!this._hidden && this.getDom()) {
              getPara(this);
              this.getDom().style.display = "none";
              this._hidden = true;
              this.fireEvent("hide")
            }
          }
        });
        var flag = 0;
        this.popup.addListener("postRenderAfter", function () {
          var popupUI = this;
          if (flag) return;
          var cont = this.getDom(), btn = cont.getElementsByTagName("button")[0];
          btn.onclick = function () {
            getPara(popupUI);
            me.editor.execCommand("autotypeset");
            popupUI.hide()
          };
          domUtils.on(cont, "click", function (e) {
            var target = e.target || e.srcElement, editorId = me.editor.uid;
            if (target && target.tagName == "INPUT") {
              if (target.name == "imageBlockLine" || target.name == "textAlign" || target.name == "symbolConver") {
                var checked = target.checked, radioTd = document.getElementById(target.name + "Value" + editorId), radios = radioTd.getElementsByTagName("input"), defalutSelect = {imageBlockLine: "none", textAlign: "left", symbolConver: "tobdc"};
                for (var i = 0; i < radios.length; i++) {
                  if (checked) {
                    if (radios[i].value == defalutSelect[target.name]) {
                      radios[i].checked = "checked"
                    }
                  } else {
                    radios[i].checked = false
                  }
                }
              }
              if (target.name == "imageBlockLineValue" + editorId || target.name == "textAlignValue" + editorId || target.name == "bdc") {
                var checkboxs = target.parentNode.previousSibling.getElementsByTagName("input");
                checkboxs && (checkboxs[0].checked = true)
              }
              getPara(popupUI)
            }
          });
          flag = 1
        });
        this.initSplitButton()
      }
    };
    utils.inherits(AutoTypeSetButton, SplitButton)
  })();
  (function () {
    var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, Stateful = baidu.editor.ui.Stateful, UIBase = baidu.editor.ui.UIBase;
    var CellAlignPicker = baidu.editor.ui.CellAlignPicker = function (options) {
      this.initOptions(options);
      this.initSelected();
      this.initCellAlignPicker()
    };
    CellAlignPicker.prototype = {
      initSelected: function () {
        var status = {valign: {top: 0, middle: 1, bottom: 2}, align: {left: 0, center: 1, right: 2}, count: 3}, result = -1;
        if (this.selected) {
          this.selectedIndex = status.valign[this.selected.valign] * status.count + status.align[this.selected.align]
        }
      }, initCellAlignPicker: function () {
        this.initUIBase();
        this.Stateful_init()
      }, getHtmlTpl: function () {
        var alignType = ["left", "center", "right"], COUNT = 9, tempClassName = null, tempIndex = -1, tmpl = [];
        for (var i = 0; i < COUNT; i++) {
          tempClassName = this.selectedIndex === i ? ' class="edui-cellalign-selected" ' : "";
          tempIndex = i % 3;
          tempIndex === 0 && tmpl.push("<tr>");
          tmpl.push('<td index="' + i + '" ' + tempClassName + ' stateful><div class="edui-icon edui-' + alignType[tempIndex] + '"></div></td>');
          tempIndex === 2 && tmpl.push("</tr>")
        }
        return '<div id="##" class="edui-cellalignpicker %%">' + '<div class="edui-cellalignpicker-body">' + '<table onclick="$$._onClick(event);">' + tmpl.join("") + "</table>" + "</div>" + "</div>"
      }, getStateDom: function () {
        return this.target
      }, _onClick: function (evt) {
        var target = evt.target || evt.srcElement;
        if (/icon/.test(target.className)) {
          this.items[target.parentNode.getAttribute("index")].onclick();
          Popup.postHide(evt)
        }
      }, _UIBase_render: UIBase.prototype.render
    };
    utils.inherits(CellAlignPicker, UIBase);
    utils.extend(CellAlignPicker.prototype, Stateful, true)
  })();
  (function () {
    var utils = baidu.editor.utils, Stateful = baidu.editor.ui.Stateful, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase;
    var PastePicker = baidu.editor.ui.PastePicker = function (options) {
      this.initOptions(options);
      this.initPastePicker()
    };
    PastePicker.prototype = {
      initPastePicker: function () {
        this.initUIBase();
        this.Stateful_init()
      }, getHtmlTpl: function () {
        return '<div class="edui-pasteicon" onclick="$$._onClick(this)"></div>' + '<div class="edui-pastecontainer">' + '<div class="edui-title">' + this.editor.getLang("pasteOpt") + "</div>" + '<div class="edui-button">' + '<div title="' + this.editor.getLang("pasteSourceFormat") + '" onclick="$$.format(false)" stateful>' + '<div class="edui-richtxticon"></div></div>' + '<div title="' + this.editor.getLang("tagFormat") + '" onclick="$$.format(2)" stateful>' + '<div class="edui-tagicon"></div></div>' + '<div title="' + this.editor.getLang("pasteTextFormat") + '" onclick="$$.format(true)" stateful>' + '<div class="edui-plaintxticon"></div></div>' + "</div>" + "</div>" + "</div>"
      }, getStateDom: function () {
        return this.target
      }, format: function (param) {
        this.editor.ui._isTransfer = true;
        this.editor.fireEvent("pasteTransfer", param)
      }, _onClick: function (cur) {
        var node = domUtils.getNextDomNode(cur), screenHt = uiUtils.getViewportRect().height, subPop = uiUtils.getClientRect(node);
        if (subPop.top + subPop.height > screenHt) node.style.top = -subPop.height - cur.offsetHeight + "px"; else node.style.top = "";
        if (/hidden/gi.test(domUtils.getComputedStyle(node, "visibility"))) {
          node.style.visibility = "visible";
          domUtils.addClass(cur, "edui-state-opened")
        } else {
          node.style.visibility = "hidden";
          domUtils.removeClasses(cur, "edui-state-opened")
        }
      }, _UIBase_render: UIBase.prototype.render
    };
    utils.inherits(PastePicker, UIBase);
    utils.extend(PastePicker.prototype, Stateful, true)
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, Toolbar = baidu.editor.ui.Toolbar = function (options) {
      this.initOptions(options);
      this.initToolbar()
    };
    Toolbar.prototype = {
      items: null, initToolbar: function () {
        this.items = this.items || [];
        this.initUIBase()
      }, add: function (item, index) {
        if (index === undefined) {
          this.items.push(item)
        } else {
          this.items.splice(index, 0, item)
        }
      }, getHtmlTpl: function () {
        var buff = [];
        for (var i = 0; i < this.items.length; i++) {
          buff[i] = this.items[i].renderHtml()
        }
        return '<div id="##" class="edui-toolbar %%" onselectstart="return false;" onmousedown="return $$._onMouseDown(event, this);">' + buff.join("") + "</div>"
      }, postRender: function () {
        var box = this.getDom();
        for (var i = 0; i < this.items.length; i++) {
          this.items[i].postRender()
        }
        uiUtils.makeUnselectable(box)
      }, _onMouseDown: function (e) {
        var target = e.target || e.srcElement, tagName = target && target.tagName && target.tagName.toLowerCase();
        if (tagName == "input" || tagName == "object" || tagName == "object") {
          return false
        }
      }
    };
    utils.inherits(Toolbar, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, Popup = baidu.editor.ui.Popup, Stateful = baidu.editor.ui.Stateful,
      CellAlignPicker = baidu.editor.ui.CellAlignPicker, QuickOperate = baidu.editor.ui.QuickOperate = function (options) {
        this.initOptions(options)
      };
    QuickOperate.prototype = {
      uiName: "quick-operate", _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, getContentHtmlTpl: function () {
        return ['<div class="edui-quick-operate">', ' <div class="edui-quick-operate-status">', '   <div class="edui-quick-operate-icon"><i class="icon icon-image"></i></div>', '   <div class="edui-quick-operate-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-icon="DragOutlined"><path d="M8.25 6.5a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5Zm0 7.25a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5Zm1.75 5.5a1.75 1.75 0 1 1-3.5 0 1.75 1.75 0 0 1 3.5 0ZM14.753 6.5a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5ZM16.5 12a1.75 1.75 0 1 1-3.5 0 1.75 1.75 0 0 1 3.5 0Zm-1.747 9a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5Z" fill="currentColor"></path></svg></div>', " </div>", ' <div class="edui-quick-operate-menu">', '   <div class="item"><i class="icon icon-image"></i> 删除</div>', '   <div class="item"><i class="icon icon-image"></i> 左对齐</div>', '   <div class="item"><i class="icon icon-image"></i> 右对齐</div>', " </div>", "</div>"].join("")
      }, destroy: function () {
        if (this.getDom()) {
          domUtils.remove(this.getDom())
        }
      }, dispose: function () {
        this.destroy()
      }
    };
    utils.inherits(QuickOperate, Popup)
  })();
  (function () {
    var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, Popup = baidu.editor.ui.Popup, Stateful = baidu.editor.ui.Stateful,
      CellAlignPicker = baidu.editor.ui.CellAlignPicker, Menu = baidu.editor.ui.Menu = function (options) {
        this.initOptions(options);
        this.initMenu()
      };
    var menuSeparator = {
      renderHtml: function () {
        return '<div class="edui-menuitem edui-menuseparator"><div class="edui-menuseparator-inner"></div></div>'
      }, postRender: function () {
      }, queryAutoHide: function () {
        return true
      }
    };
    Menu.prototype = {
      items: null, uiName: "menu", initMenu: function () {
        this.items = this.items || [];
        this.initPopup();
        this.initItems()
      }, initItems: function () {
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          if (item == "-") {
            this.items[i] = this.getSeparator()
          } else if (!(item instanceof MenuItem)) {
            item.editor = this.editor;
            item.theme = this.editor.options.theme;
            this.items[i] = this.createItem(item)
          }
        }
      }, getSeparator: function () {
        return menuSeparator
      }, createItem: function (item) {
        item.menu = this;
        return new MenuItem(item)
      }, _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, getContentHtmlTpl: function () {
        if (this.items.length == 0) {
          return this._Popup_getContentHtmlTpl()
        }
        var buff = [];
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          buff[i] = item.renderHtml()
        }
        return '<div class="%%-body">' + buff.join("") + "</div>"
      }, _Popup_postRender: Popup.prototype.postRender, postRender: function () {
        var me = this;
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          item.ownerMenu = this;
          item.postRender()
        }
        domUtils.on(this.getDom(), "mouseover", function (evt) {
          evt = evt || event;
          var rel = evt.relatedTarget || evt.fromElement;
          var el = me.getDom();
          if (!uiUtils.contains(el, rel) && el !== rel) {
            me.fireEvent("over")
          }
        });
        this._Popup_postRender()
      }, queryAutoHide: function (el) {
        if (el) {
          if (uiUtils.contains(this.getDom(), el)) {
            return false
          }
          for (var i = 0; i < this.items.length; i++) {
            var item = this.items[i];
            if (item.queryAutoHide(el) === false) {
              return false
            }
          }
        }
      }, clearItems: function () {
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          clearTimeout(item._showingTimer);
          clearTimeout(item._closingTimer);
          if (item.subMenu) {
            item.subMenu.destroy()
          }
        }
        this.items = []
      }, destroy: function () {
        if (this.getDom()) {
          domUtils.remove(this.getDom())
        }
        this.clearItems()
      }, dispose: function () {
        this.destroy()
      }
    };
    utils.inherits(Menu, Popup);
    var MenuItem = baidu.editor.ui.MenuItem = function (options) {
      this.initOptions(options);
      this.initUIBase();
      this.Stateful_init();
      if (this.subMenu && !(this.subMenu instanceof Menu)) {
        if (options.className && options.className.indexOf("aligntd") != -1) {
          var me = this;
          this.subMenu.selected = this.editor.queryCommandValue("cellalignment");
          this.subMenu = new Popup({
            content: new CellAlignPicker(this.subMenu), parentMenu: me, editor: me.editor, destroy: function () {
              if (this.getDom()) {
                domUtils.remove(this.getDom())
              }
            }
          });
          this.subMenu.addListener("postRenderAfter", function () {
            domUtils.on(this.getDom(), "mouseover", function () {
              me.addState("opened")
            })
          })
        } else {
          this.subMenu = new Menu(this.subMenu)
        }
      }
    };
    MenuItem.prototype = {
      label: "", subMenu: null, ownerMenu: null, uiName: "menuitem", alwalysHoverable: true, getHtmlTpl: function () {
        return '<div id="##" class="%%" stateful onclick="$$._onClick(event, this);">' + '<div class="%%-body">' + this.renderLabelHtml() + "</div>" + "</div>"
      }, postRender: function () {
        var me = this;
        this.addListener("over", function () {
          me.ownerMenu.fireEvent("submenuover", me);
          if (me.subMenu) {
            me.delayShowSubMenu()
          }
        });
        if (this.subMenu) {
          this.getDom().className += " edui-hassubmenu";
          this.subMenu.render();
          this.addListener("out", function () {
            me.delayHideSubMenu()
          });
          this.subMenu.addListener("over", function () {
            clearTimeout(me._closingTimer);
            me._closingTimer = null;
            me.addState("opened")
          });
          this.ownerMenu.addListener("hide", function () {
            me.hideSubMenu()
          });
          this.ownerMenu.addListener("submenuover", function (t, subMenu) {
            if (subMenu !== me) {
              me.delayHideSubMenu()
            }
          });
          this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide;
          this.subMenu.queryAutoHide = function (el) {
            if (el && uiUtils.contains(me.getDom(), el)) {
              return false
            }
            return this._bakQueryAutoHide(el)
          }
        }
        this.getDom().style.tabIndex = "-1";
        uiUtils.makeUnselectable(this.getDom());
        this.Stateful_postRender()
      }, delayShowSubMenu: function () {
        var me = this;
        if (!me.isDisabled()) {
          me.addState("opened");
          clearTimeout(me._showingTimer);
          clearTimeout(me._closingTimer);
          me._closingTimer = null;
          me._showingTimer = setTimeout(function () {
            me.showSubMenu()
          }, 250)
        }
      }, delayHideSubMenu: function () {
        var me = this;
        if (!me.isDisabled()) {
          me.removeState("opened");
          clearTimeout(me._showingTimer);
          if (!me._closingTimer) {
            me._closingTimer = setTimeout(function () {
              if (!me.hasState("opened")) {
                me.hideSubMenu()
              }
              me._closingTimer = null
            }, 400)
          }
        }
      }, renderLabelHtml: function () {
        return '<div class="edui-arrow"></div>' + '<div class="edui-box edui-icon"></div>' + '<div class="edui-box edui-label %%-label">' + (this.label || "") + "</div>"
      }, getStateDom: function () {
        return this.getDom()
      }, queryAutoHide: function (el) {
        if (this.subMenu && this.hasState("opened")) {
          return this.subMenu.queryAutoHide(el)
        }
      }, _onClick: function (event, this_) {
        if (this.hasState("disabled")) return;
        if (this.fireEvent("click", event, this_) !== false) {
          if (this.subMenu) {
            this.showSubMenu()
          } else {
            Popup.postHide(event)
          }
        }
      }, showSubMenu: function () {
        var rect = uiUtils.getClientRect(this.getDom());
        rect.right -= 5;
        rect.left += 2;
        rect.width -= 7;
        rect.top -= 4;
        rect.bottom += 4;
        rect.height += 8;
        this.subMenu.showAnchorRect(rect, true, true)
      }, hideSubMenu: function () {
        this.subMenu.hide()
      }
    };
    utils.inherits(MenuItem, UIBase);
    utils.extend(MenuItem.prototype, Stateful, true)
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, Menu = baidu.editor.ui.Menu, SplitButton = baidu.editor.ui.SplitButton, Combox = baidu.editor.ui.Combox = function (options) {
      this.initOptions(options);
      this.initCombox()
    };
    Combox.prototype = {
      uiName: "combox", onbuttonclick: function () {
        this.showPopup()
      }, initCombox: function () {
        var me = this;
        this.items = this.items || [];
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          item.uiName = "listitem";
          item.index = i;
          item.onclick = function () {
            me.selectByIndex(this.index)
          }
        }
        this.popup = new Menu({items: this.items, uiName: "list", editor: this.editor, captureWheel: true, combox: this});
        this.initSplitButton()
      }, _SplitButton_postRender: SplitButton.prototype.postRender, postRender: function () {
        this._SplitButton_postRender();
        this.setLabel(this.label || "");
        this.setValue(this.initValue || "")
      }, showPopup: function () {
        var rect = uiUtils.getClientRect(this.getDom());
        rect.top += 1;
        rect.bottom -= 1;
        rect.height -= 2;
        this.popup.showAnchorRect(rect)
      }, getValue: function () {
        return this.value
      }, setValue: function (value) {
        var index = this.indexByValue(value);
        if (index != -1) {
          this.selectedIndex = index;
          this.setLabel(this.items[index].label);
          this.value = this.items[index].value
        } else {
          this.selectedIndex = -1;
          this.setLabel(this.getLabelForUnknowValue(value));
          this.value = value
        }
      }, setLabel: function (label) {
        this.getDom("button_body").innerHTML = label;
        this.label = label
      }, getLabelForUnknowValue: function (value) {
        return value
      }, indexByValue: function (value) {
        for (var i = 0; i < this.items.length; i++) {
          if (value == this.items[i].value) {
            return i
          }
        }
        return -1
      }, getItem: function (index) {
        return this.items[index]
      }, selectByIndex: function (index) {
        if (index < this.items.length && this.fireEvent("select", index) !== false) {
          this.selectedIndex = index;
          this.value = this.items[index].value;
          this.setLabel(this.items[index].label)
        }
      }
    };
    utils.inherits(Combox, SplitButton)
  })();
  (function () {
    var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils, Mask = baidu.editor.ui.Mask, UIBase = baidu.editor.ui.UIBase, Button = baidu.editor.ui.Button,
      Dialog = baidu.editor.ui.Dialog = function (options) {
        if (options.name) {
          var name = options.name;
          var cssRules = options.cssRules;
          if (!options.className) {
            options.className = "edui-for-" + name
          }
          if (cssRules) {
            options.cssRules = ".edui-for-" + name + " .edui-dialog-content  {" + cssRules + "}"
          }
        }
        this.initOptions(utils.extend({
          autoReset: true, draggable: true, onok: function () {
          }, oncancel: function () {
          }, onclose: function (t, ok) {
            return ok ? this.onok() : this.oncancel()
          }, holdScroll: false
        }, options));
        this.initDialog()
      };
    var modalMask;
    var dragMask;
    var activeDialog;
    Dialog.prototype = {
      draggable: false, uiName: "dialog", initDialog: function () {
        var me = this, theme = this.editor.options.theme;
        if (this.cssRules) {
          this.cssRules = ".edui-" + theme + " " + this.cssRules;
          utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules)
        }
        this.initUIBase();
        this.modalMask = modalMask || (modalMask = new Mask({
          className: "edui-dialog-modalmask", theme: theme, onclick: function () {
            activeDialog && activeDialog.close(false)
          }
        }));
        this.dragMask = dragMask || (dragMask = new Mask({className: "edui-dialog-dragmask", theme: theme}));
        this.closeButton = new Button({
          className: "edui-dialog-closebutton", title: me.closeDialog, theme: theme, onclick: function () {
            me.close(false)
          }
        });
        this.fullscreen && this.initResizeEvent();
        if (this.buttons) {
          for (var i = 0; i < this.buttons.length; i++) {
            if (!(this.buttons[i] instanceof Button)) {
              this.buttons[i] = new Button(utils.extend(this.buttons[i], {editor: this.editor}, true))
            }
          }
        }
      }, initResizeEvent: function () {
        var me = this;
        domUtils.on(window, "resize", function () {
          if (me._hidden || me._hidden === undefined) {
            return
          }
          if (me.__resizeTimer) {
            window.clearTimeout(me.__resizeTimer)
          }
          me.__resizeTimer = window.setTimeout(function () {
            me.__resizeTimer = null;
            var dialogWrapNode = me.getDom(), contentNode = me.getDom("content"), wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), contentRect = UE.ui.uiUtils.getClientRect(contentNode), vpRect = uiUtils.getViewportRect();
            contentNode.style.width = vpRect.width - wrapRect.width + contentRect.width + "px";
            contentNode.style.height = vpRect.height - wrapRect.height + contentRect.height + "px";
            dialogWrapNode.style.width = vpRect.width + "px";
            dialogWrapNode.style.height = vpRect.height + "px";
            me.fireEvent("resize")
          }, 100)
        })
      }, fitSize: function () {
        var popBodyEl = this.getDom("body");
        var $foot = popBodyEl.querySelector(".edui-dialog-foot");
        var heightWithoutBody = 70;
        if (!$foot) {
          heightWithoutBody = 30
        }
        var size = this.mesureSize();
        var winSize = uiUtils.getViewportRect();
        var width = size.width;
        var height = size.height - heightWithoutBody;
        var maxWidth = winSize.width - 2;
        var maxHeight = winSize.height - heightWithoutBody - 2;
        if (width > maxWidth) {
          height = height * maxWidth / width;
          width = maxWidth
        }
        if (height > maxHeight) {
          width = width * maxHeight / height;
          height = maxHeight
        }
        var scale = width / size.width;
        var $content = popBodyEl.querySelector(".edui-dialog-content");
        if (!$content.dataset.dialogScaled) {
          $content.dataset.dialogScaled = true;
          $content.style.width = width + "px";
          $content.style.height = height + "px";
          var $iframe = popBodyEl.querySelector(".edui-dialog-content iframe");
          $iframe.style.width = size.width + "px";
          $iframe.style.height = size.height - heightWithoutBody + "px";
          $iframe.style.transformOrigin = "0 0";
          $iframe.style.transform = "scale(" + scale + ")";
          size.width = width;
          size.height = height + heightWithoutBody
        }
        popBodyEl.style.width = size.width + "px";
        popBodyEl.style.height = size.height + "px";
        return size
      }, safeSetOffset: function (offset) {
        var me = this;
        var el = me.getDom();
        var vpRect = uiUtils.getViewportRect();
        var rect = uiUtils.getClientRect(el);
        var left = offset.left;
        if (left + rect.width > vpRect.right) {
          left = vpRect.right - rect.width
        }
        var top = offset.top;
        if (top + rect.height > vpRect.bottom) {
          top = vpRect.bottom - rect.height
        }
        el.style.left = Math.max(left, 0) + "px";
        el.style.top = Math.max(top, 0) + "px"
      }, showAtCenter: function () {
        var vpRect = uiUtils.getViewportRect();
        if (!this.fullscreen) {
          this.getDom().style.display = "";
          var popSize = this.fitSize();
          var titleHeight = this.getDom("titlebar").offsetHeight | 0;
          var left = vpRect.width / 2 - popSize.width / 2;
          var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight;
          var popEl = this.getDom();
          this.safeSetOffset({left: Math.max(left | 0, 0), top: Math.max(top | 0, 0)});
          if (!domUtils.hasClass(popEl, "edui-state-centered")) {
            popEl.className += " edui-state-centered"
          }
        } else {
          var dialogWrapNode = this.getDom(), contentNode = this.getDom("content");
          dialogWrapNode.style.display = "block";
          var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), contentRect = UE.ui.uiUtils.getClientRect(contentNode);
          dialogWrapNode.style.left = "-100000px";
          contentNode.style.width = vpRect.width - wrapRect.width + contentRect.width + "px";
          contentNode.style.height = vpRect.height - wrapRect.height + contentRect.height + "px";
          dialogWrapNode.style.width = vpRect.width + "px";
          dialogWrapNode.style.height = vpRect.height + "px";
          dialogWrapNode.style.left = 0;
          this._originalContext = {html: {overflowX: document.documentElement.style.overflowX, overflowY: document.documentElement.style.overflowY}, body: {overflowX: document.body.style.overflowX, overflowY: document.body.style.overflowY}};
          document.documentElement.style.overflowX = "hidden";
          document.documentElement.style.overflowY = "hidden";
          document.body.style.overflowX = "hidden";
          document.body.style.overflowY = "hidden"
        }
        this._show()
      }, getContentHtml: function () {
        var contentHtml = "";
        if (typeof this.content == "string") {
          contentHtml = this.content
        } else if (this.iframeUrl) {
          contentHtml = '<span id="' + this.id + '_contmask" class="dialogcontmask"></span><iframe id="' + this.id + '_iframe" class="%%-iframe" height="100%" width="100%" frameborder="0" src="' + this.iframeUrl + '"></iframe>'
        }
        return contentHtml
      }, getHtmlTpl: function () {
        var footHtml = "";
        if (this.buttons) {
          var buff = [];
          for (var i = 0; i < this.buttons.length; i++) {
            buff[i] = this.buttons[i].renderHtml()
          }
          footHtml = '<div class="%%-foot">' + '<div id="##_buttons" class="%%-buttons">' + buff.join("") + "</div>" + "</div>"
        }
        return '<div id="##" class="%%"><div ' + (!this.fullscreen ? 'class="%%"' : 'class="%%-wrap edui-dialog-fullscreen-flag"') + '><div id="##_body" class="%%-body">' + '<div class="%%-shadow"></div>' + '<div id="##_titlebar" class="%%-titlebar">' + '<div class="%%-draghandle" onmousedown="$$._onTitlebarMouseDown(event, this);">' + '<span class="%%-caption">' + (this.title || "") + "</span>" + "</div>" + this.closeButton.renderHtml() + "</div>" + '<div id="##_content" class="%%-content">' + (this.autoReset ? "" : this.getContentHtml()) + "</div>" + footHtml + "</div></div></div>"
      }, postRender: function () {
        if (!this.modalMask.getDom()) {
          this.modalMask.render();
          this.modalMask.hide()
        }
        if (!this.dragMask.getDom()) {
          this.dragMask.render();
          this.dragMask.hide()
        }
        var me = this;
        this.addListener("show", function () {
          me.modalMask.show(this.getDom().style.zIndex - 2)
        });
        this.addListener("hide", function () {
          me.modalMask.hide()
        });
        if (this.buttons) {
          for (var i = 0; i < this.buttons.length; i++) {
            this.buttons[i].postRender()
          }
        }
        domUtils.on(window, "resize", function () {
          setTimeout(function () {
            if (!me.isHidden()) {
              me.safeSetOffset(uiUtils.getClientRect(me.getDom()))
            }
          })
        });
        this._hide()
      }, mesureSize: function () {
        var body = this.getDom("body");
        var width = uiUtils.getClientRect(this.getDom("content")).width;
        var dialogBodyStyle = body.style;
        dialogBodyStyle.width = width;
        return uiUtils.getClientRect(body)
      }, _onTitlebarMouseDown: function (evt, el) {
        if (this.draggable) {
          var rect;
          var vpRect = uiUtils.getViewportRect();
          var me = this;
          uiUtils.startDrag(evt, {
            ondragstart: function () {
              rect = uiUtils.getClientRect(me.getDom());
              me.getDom("contmask").style.visibility = "visible";
              me.dragMask.show(me.getDom().style.zIndex - 1)
            }, ondragmove: function (x, y) {
              var left = rect.left + x;
              var top = rect.top + y;
              me.safeSetOffset({left: left, top: top})
            }, ondragstop: function () {
              me.getDom("contmask").style.visibility = "hidden";
              domUtils.removeClasses(me.getDom(), ["edui-state-centered"]);
              me.dragMask.hide()
            }
          })
        }
      }, reset: function () {
        this.getDom("content").innerHTML = this.getContentHtml();
        this.fireEvent("dialogafterreset")
      }, _show: function () {
        if (this._hidden) {
          this.getDom().style.display = "";
          this.editor.container.style.zIndex && (this.getDom().style.zIndex = this.editor.container.style.zIndex * 1 + 10);
          this._hidden = false;
          this.fireEvent("show");
          baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = this.getDom().style.zIndex - 4
        }
      }, isHidden: function () {
        return this._hidden
      }, _hide: function () {
        if (!this._hidden) {
          var wrapNode = this.getDom();
          wrapNode.style.display = "none";
          wrapNode.style.zIndex = "";
          wrapNode.style.width = "";
          wrapNode.style.height = "";
          this._hidden = true;
          this.fireEvent("hide")
        }
      }, open: function () {
        if (this.autoReset) {
          try {
            this.reset()
          } catch (e) {
            this.render();
            this.open()
          }
        }
        this.showAtCenter();
        if (this.iframeUrl) {
          try {
            this.getDom("iframe").focus()
          } catch (ex) {
          }
        }
        activeDialog = this
      }, _onCloseButtonClick: function (evt, el) {
        this.close(false)
      }, close: function (ok) {
        if (this.fireEvent("close", ok) !== false) {
          if (this.fullscreen) {
            document.documentElement.style.overflowX = this._originalContext.html.overflowX;
            document.documentElement.style.overflowY = this._originalContext.html.overflowY;
            document.body.style.overflowX = this._originalContext.body.overflowX;
            document.body.style.overflowY = this._originalContext.body.overflowY;
            delete this._originalContext
          }
          this._hide();
          var content = this.getDom("content");
          var iframe = this.getDom("iframe");
          if (content && iframe) {
            var doc = iframe.contentDocument || iframe.contentWindow.document;
            doc && (doc.body.innerHTML = "");
            domUtils.remove(content)
          }
        }
      }
    };
    utils.inherits(Dialog, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils, Menu = baidu.editor.ui.Menu, SplitButton = baidu.editor.ui.SplitButton, MenuButton = baidu.editor.ui.MenuButton = function (options) {
      this.initOptions(options);
      this.initMenuButton()
    };
    MenuButton.prototype = {
      initMenuButton: function () {
        var me = this;
        this.uiName = "menubutton";
        this.popup = new Menu({items: me.items, className: me.className, editor: me.editor});
        this.popup.addListener("show", function () {
          var list = this;
          for (var i = 0; i < list.items.length; i++) {
            list.items[i].removeState("checked");
            if (list.items[i].value == me._value) {
              list.items[i].addState("checked");
              this.value = me._value
            }
          }
        });
        this.initSplitButton()
      }, setValue: function (value) {
        this._value = value
      }
    };
    utils.inherits(MenuButton, SplitButton)
  })();
  (function () {
    var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, SplitButton = baidu.editor.ui.SplitButton, MultiMenuPop = baidu.editor.ui.MultiMenuPop = function (options) {
      this.initOptions(options);
      this.initMultiMenu()
    };
    MultiMenuPop.prototype = {
      initMultiMenu: function () {
        var me = this;
        this.popup = new Popup({
          content: "", editor: me.editor, iframe_rendered: false, onshow: function () {
            if (!this.iframe_rendered) {
              this.iframe_rendered = true;
              this.getDom("content").innerHTML = '<iframe id="' + me.id + '_iframe" src="' + me.iframeUrl + '" frameborder="0"></iframe>';
              me.editor.container.style.zIndex && (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1)
            }
          }
        });
        this.onbuttonclick = function () {
          this.showPopup()
        };
        this.initSplitButton()
      }
    };
    utils.inherits(MultiMenuPop, SplitButton)
  })();
  (function () {
    var UI = baidu.editor.ui, UIBase = UI.UIBase, uiUtils = UI.uiUtils, utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils;
    var allMenus = [], timeID, isSubMenuShow = false;
    var ShortCutMenu = UI.ShortCutMenu = function (options) {
      this.initOptions(options);
      this.initShortCutMenu()
    };
    ShortCutMenu.postHide = hideAllMenu;
    ShortCutMenu.prototype = {
      isHidden: true, SPACE: 5, initShortCutMenu: function () {
        this.items = this.items || [];
        this.initUIBase();
        this.initItems();
        this.initEvent();
        allMenus.push(this)
      }, initEvent: function () {
        var me = this, doc = me.editor.document;
        me.editor.addListener("afterhidepop", function () {
          if (!me.isHidden) {
            isSubMenuShow = true
          }
        })
      }, initItems: function () {
        if (utils.isArray(this.items)) {
          for (var i = 0, len = this.items.length; i < len; i++) {
            if ("string" !== typeof this.items[i]) {
              continue
            }
            var item = this.items[i].toLowerCase();
            if (UI[item]) {
              this.items[i] = new UI[item](this.editor);
              this.items[i].className += " edui-short-cut-sub-menu "
            }
          }
        }
      }, setOpacity: function (el, value) {
        if (browser.ie && browser.version < 9) {
          el.style.filter = "alpha(opacity = " + parseFloat(value) * 100 + ");"
        } else {
          el.style.opacity = value
        }
      }, getSubMenuMark: function () {
        isSubMenuShow = false;
        var layerEle = uiUtils.getFixedLayer();
        var list = domUtils.getElementsByTagName(layerEle, "div", function (node) {
          return domUtils.hasClass(node, "edui-short-cut-sub-menu edui-popup")
        });
        for (var i = 0, node; node = list[i++];) {
          if (node.style.display !== "none") {
            isSubMenuShow = true
          }
        }
        return isSubMenuShow
      }, show: function (e, hasContextmenu) {
        var me = this, offset = {}, el = this.getDom(), fixedlayer = uiUtils.getFixedLayer();
        for (let item of this.items) {
          if ("shouldUiShow" in item) {
            item.uiShow(item.shouldUiShow())
          }
        }

        function setPos(offset) {
          if (offset.left < 0) {
            offset.left = 0
          }
          if (offset.top < 0) {
            offset.top = 0
          }
          el.style.cssText = "position:absolute;left:" + offset.left + "px;top:" + offset.top + "px;"
        }

        function setPosByCxtMenu(menu) {
          if (!menu.tagName) {
            menu = menu.getDom()
          }
          offset.left = parseInt(menu.style.left);
          offset.top = parseInt(menu.style.top);
          offset.top -= el.offsetHeight + 15;
          setPos(offset)
        }

        me.eventType = e.type;
        el.style.cssText = "display:block;left:-9999px";
        offset = uiUtils.getViewportOffsetByEvent(e);
        offset.top -= el.offsetHeight + me.SPACE;
        offset.left += me.SPACE + 20;
        setPos(offset);
        me.setOpacity(el, 1);
        me.isHidden = false;
        me.left = e.screenX + el.offsetWidth / 2 - me.SPACE;
        me.top = e.screenY - el.offsetHeight / 2 - me.SPACE;
        if (me.editor) {
          el.style.zIndex = me.editor.container.style.zIndex * 1 + 10;
          fixedlayer.style.zIndex = el.style.zIndex - 1
        }
      }, hide: function () {
        if (this.getDom()) {
          this.getDom().style.display = "none"
        }
        this.isHidden = true
      }, postRender: function () {
        if (utils.isArray(this.items)) {
          for (var i = 0, item; item = this.items[i++];) {
            item.postRender()
          }
        }
      }, getHtmlTpl: function () {
        var buff;
        if (utils.isArray(this.items)) {
          buff = [];
          for (var i = 0; i < this.items.length; i++) {
            buff[i] = this.items[i].renderHtml()
          }
          buff = buff.join("")
        } else {
          buff = this.items
        }
        return '<div id="##" class="%% edui-toolbar" data-src="shortcutmenu" onmousedown="return false;" onselectstart="return false;" >' + buff + "</div>"
      }
    };
    utils.inherits(ShortCutMenu, UIBase);

    function hideAllMenu(e) {
      var tgt = e.target || e.srcElement, cur = domUtils.findParent(tgt, function (node) {
        return domUtils.hasClass(node, "edui-shortcutmenu") || domUtils.hasClass(node, "edui-popup")
      }, true);
      if (!cur) {
        for (var i = 0, menu; menu = allMenus[i++];) {
          menu.hide()
        }
      }
    }

    domUtils.on(document, "mousedown", function (e) {
      hideAllMenu(e)
    });
    domUtils.on(window, "scroll", function (e) {
      hideAllMenu(e)
    })
  })();
  (function () {
    var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Breakline = baidu.editor.ui.Breakline = function (options) {
      this.initOptions(options);
      this.initSeparator()
    };
    Breakline.prototype = {
      uiName: "Breakline", initSeparator: function () {
        this.initUIBase()
      }, getHtmlTpl: function () {
        return "<br/>"
      }
    };
    utils.inherits(Breakline, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Message = baidu.editor.ui.Message = function (options) {
      this.initOptions(options);
      this.initMessage()
    };
    Message.prototype = {
      initMessage: function () {
        this.initUIBase()
      }, getHtmlTpl: function () {
        return '<div id="##" class="edui-message %%">' + ' <div id="##_closer" class="edui-message-closer">×</div>' + ' <div id="##_body" class="edui-message-body edui-message-type-info">' + ' <iframe style="position:absolute;z-index:-1;left:0;top:0;background-color: transparent;" frameborder="0" width="100%" height="100%" src="about:blank"></iframe>' + ' <div class="edui-shadow"></div>' + ' <div id="##_content" class="edui-message-content">' + "  </div>" + " </div>" + "</div>"
      }, reset: function (opt) {
        var me = this;
        if (!opt.keepshow) {
          clearTimeout(this.timer);
          me.timer = setTimeout(function () {
            me.hide()
          }, opt.timeout || 4e3)
        }
        opt.content !== undefined && me.setContent(opt.content);
        opt.type !== undefined && me.setType(opt.type);
        me.show()
      }, postRender: function () {
        var me = this, closer = this.getDom("closer");
        closer && domUtils.on(closer, "click", function () {
          me.hide()
        })
      }, setContent: function (content) {
        this.getDom("content").innerHTML = content
      }, setType: function (type) {
        type = type || "info";
        var body = this.getDom("body");
        body.className = body.className.replace(/edui-message-type-[\w-]+/, "edui-message-type-" + type)
      }, getContent: function () {
        return this.getDom("content").innerHTML
      }, getType: function () {
        var arr = this.getDom("body").match(/edui-message-type-([\w-]+)/);
        return arr ? arr[1] : ""
      }, show: function () {
        this.getDom().style.display = "block"
      }, hide: function () {
        var dom = this.getDom();
        if (dom) {
          dom.style.display = "none";
          dom.parentNode && dom.parentNode.removeChild(dom)
        }
      }
    };
    utils.inherits(Message, UIBase)
  })();
  (function () {
    var utils = baidu.editor.utils;
    var editorui = baidu.editor.ui;
    var _Dialog = editorui.Dialog;
    editorui.buttons = {};
    editorui.Dialog = function (options) {
      var dialog = new _Dialog(options);
      dialog.addListener("hide", function () {
        if (dialog.editor) {
          var editor = dialog.editor;
          try {
            if (browser.gecko) {
              var y = editor.window.scrollY, x = editor.window.scrollX;
              editor.body.focus();
              editor.window.scrollTo(x, y)
            } else {
              editor.focus()
            }
          } catch (ex) {
          }
        }
      });
      return dialog
    };
    var btnCmds = ["undo", "redo", "formatmatch", "bold", "italic", "underline", "fontborder", "touppercase", "tolowercase", "strikethrough", "subscript", "superscript", "source", "indent", "outdent", "blockquote", "pasteplain", "pagebreak", "selectall", "print", "horizontal", "removeformat", "time", "date", "unlink", "insertparagraphbeforetable", "insertrow", "insertcol", "mergeright", "mergedown", "deleterow", "deletecol", "splittorows", "splittocols", "splittocells", "mergecells", "deletetable"];
    for (var i = 0, ci; ci = btnCmds[i++];) {
      ci = ci.toLowerCase();
      editorui[ci] = function (cmd) {
        return function (editor) {
          var ui = new editorui.Button({
            className: "edui-for-" + cmd, title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || "", onclick: function () {
              editor.execCommand(cmd)
            }, theme: editor.options.theme, showText: false
          });
          switch (cmd) {
            case"bold":
            case"italic":
            case"underline":
            case"strikethrough":
            case"fontborder":
              ui.shouldUiShow = function (cmdInternal) {
                return function () {
                  if (!editor.selection.getText()) {
                    return false
                  }
                  return editor.queryCommandState(cmdInternal) !== UE.constants.STATEFUL.DISABLED
                }
              }(cmd);
              break
          }
          editorui.buttons[cmd] = ui;
          editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
            var state = editor.queryCommandState(cmd);
            if (state === -1) {
              ui.setDisabled(true);
              ui.setChecked(false)
            } else {
              if (!uiReady) {
                ui.setDisabled(false);
                ui.setChecked(state)
              }
            }
          });
          return ui
        }
      }(ci)
    }
    editorui.cleardoc = function (editor) {
      var ui = new editorui.Button({
        className: "edui-for-cleardoc", title: editor.options.labelMap.cleardoc || editor.getLang("labelMap.cleardoc") || "", theme: editor.options.theme, onclick: function () {
          if (confirm(editor.getLang("confirmClear"))) {
            editor.execCommand("cleardoc")
          }
        }
      });
      editorui.buttons["cleardoc"] = ui;
      editor.addListener("selectionchange", function () {
        ui.setDisabled(editor.queryCommandState("cleardoc") == -1)
      });
      return ui
    };
    var imageTypeSet = ["none", "left", "center", "right"];
    for (let value of imageTypeSet) {
      (function (value) {
        editorui["image" + value] = function (editor) {
          var ui = new editorui.Button({
            className: "edui-for-" + "image" + value, title: editor.options.labelMap["image" + value] || editor.getLang("labelMap." + "image" + value) || "", theme: editor.options.theme, onclick: function () {
              editor.execCommand("imagefloat", value)
            }, shouldUiShow: function () {
              let closedNode = editor.selection.getRange().getClosedNode();
              if (!closedNode || closedNode.tagName !== "IMG") {
                return false
              }
              if (domUtils.hasClass(closedNode, "uep-loading") || domUtils.hasClass(closedNode, "uep-loading-error")) {
                return false
              }
              return editor.queryCommandState("imagefloat") !== UE.constants.STATEFUL.DISABLED
            }
          });
          editorui.buttons["image" + value] = ui;
          editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
            ui.setDisabled(editor.queryCommandState("imagefloat") === UE.constants.STATEFUL.DISABLED);
            ui.setChecked(editor.queryCommandValue("imagefloat") === value && !uiReady)
          });
          return ui
        }
      })(value)
    }
    var typeset = {justify: ["left", "right", "center", "justify"], directionality: ["ltr", "rtl"]};
    for (var p in typeset) {
      (function (cmd, val) {
        for (var i = 0, ci; ci = val[i++];) {
          (function (cmd2) {
            editorui[cmd.replace("float", "") + cmd2] = function (editor) {
              var ui = new editorui.Button({
                className: "edui-for-" + cmd.replace("float", "") + cmd2,
                title: editor.options.labelMap[cmd.replace("float", "") + cmd2] || editor.getLang("labelMap." + cmd.replace("float", "") + cmd2) || "",
                theme: editor.options.theme,
                onclick: function () {
                  editor.execCommand(cmd, cmd2)
                }
              });
              editorui.buttons[cmd] = ui;
              editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
                ui.setDisabled(editor.queryCommandState(cmd) == -1);
                ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady)
              });
              return ui
            }
          })(ci)
        }
      })(p, typeset[p])
    }
    for (var i = 0, ci; ci = ["backcolor", "forecolor"][i++];) {
      editorui[ci] = function (cmd) {
        return function (editor) {
          var ui = new editorui.ColorButton({
            className: "edui-for-" + cmd, color: "default", title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || "", editor: editor, onpickcolor: function (t, color) {
              editor.execCommand(cmd, color)
            }, onpicknocolor: function () {
              editor.execCommand(cmd, "default");
              this.setColor("transparent");
              this.color = "default"
            }, onbuttonclick: function () {
              editor.execCommand(cmd, this.color)
            }, shouldUiShow: function () {
              if (!editor.selection.getText()) {
                return false
              }
              return editor.queryCommandState(cmd) !== UE.constants.STATEFUL.DISABLED
            }
          });
          editorui.buttons[cmd] = ui;
          editor.addListener("selectionchange", function () {
            ui.setDisabled(editor.queryCommandState(cmd) == -1)
          });
          return ui
        }
      }(ci)
    }
    var dialogIframeUrlMap = {
      anchor: "~/dialogs/anchor/anchor.html?2f10d082",
      insertimage: "~/dialogs/image/image.html?62e5392c",
      link: "~/dialogs/link/link.html?ccbfcf18",
      spechars: "~/dialogs/spechars/spechars.html?3bbeb696",
      searchreplace: "~/dialogs/searchreplace/searchreplace.html?2cb782d2",
      insertvideo: "~/dialogs/video/video.html?1603eb78",
      insertaudio: "~/dialogs/audio/audio.html?a2979235",
      help: "~/dialogs/help/help.html?05c0c8bf",
      preview: "~/dialogs/preview/preview.html?5d9a0847",
      emotion: "~/dialogs/emotion/emotion.html?a7bc0989",
      wordimage: "~/dialogs/wordimage/wordimage.html?e6ca77bb",
      formula: "~/dialogs/formula/formula.html?9a5a1511",
      attachment: "~/dialogs/attachment/attachment.html?5cd272ea",
      insertframe: "~/dialogs/insertframe/insertframe.html?807119a5",
      edittip: "~/dialogs/table/edittip.html?fa0ea189",
      edittable: "~/dialogs/table/edittable.html?134e2f06",
      edittd: "~/dialogs/table/edittd.html?9fe1a06e",
      scrawl: "~/dialogs/scrawl/scrawl.html?81bccab9",
      template: "~/dialogs/template/template.html?3c8090b7",
      background: "~/dialogs/background/background.html?c2bb8b05",
      contentimport: "~/dialogs/contentimport/contentimport.html?e298f77b"
    };
    var dialogBtns = {
      noOk: ["searchreplace", "help", "spechars", "preview"],
      ok: ["attachment", "anchor", "link", "insertimage", "insertframe", "wordimage", "insertvideo", "insertaudio", "edittip", "edittable", "edittd", "scrawl", "template", "formula", "background", "contentimport"]
    };
    for (var p in dialogBtns) {
      (function (type, vals) {
        for (var i = 0, ci; ci = vals[i++];) {
          if (browser.opera && ci === "searchreplace") {
            continue
          }
          (function (cmd) {
            editorui[cmd] = function (editor, iframeUrl, title) {
              iframeUrl = iframeUrl || (editor.options.dialogIframeUrlMap || {})[cmd] || dialogIframeUrlMap[cmd];
              title = editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || "";
              var dialog;
              if (iframeUrl) {
                dialog = new editorui.Dialog(utils.extend({
                  iframeUrl: editor.ui.mapUrl(iframeUrl),
                  editor: editor,
                  className: "edui-for-" + cmd,
                  title: title,
                  holdScroll: cmd === "insertimage",
                  fullscreen: /preview/.test(cmd),
                  closeDialog: editor.getLang("closeDialog")
                }, type === "ok" ? {
                  buttons: [{
                    className: "edui-okbutton", label: editor.getLang("ok"), editor: editor, onclick: function () {
                      dialog.close(true)
                    }
                  }, {
                    className: "edui-cancelbutton", label: editor.getLang("cancel"), editor: editor, onclick: function () {
                      dialog.close(false)
                    }
                  }]
                } : {}));
                editor.ui._dialogs[cmd + "Dialog"] = dialog
              }
              var ui = new editorui.Button({
                className: "edui-for-" + cmd, title: title, onclick: function () {
                  if (editor.options.toolbarCallback) {
                    if (true === editor.options.toolbarCallback(cmd, editor)) {
                      return
                    }
                  }
                  if (dialog) {
                    switch (cmd) {
                      case"wordimage":
                        var images = editor.execCommand("wordimage");
                        if (images && images.length) {
                          dialog.render();
                          dialog.open()
                        }
                        break;
                      case"scrawl":
                        if (editor.queryCommandState("scrawl") !== -1) {
                          dialog.render();
                          dialog.open()
                        }
                        break;
                      default:
                        dialog.render();
                        dialog.open()
                    }
                  }
                }, theme: editor.options.theme, disabled: cmd === "scrawl" && editor.queryCommandState("scrawl") === -1
              });
              switch (cmd) {
                case"insertimage":
                case"formula":
                  ui.shouldUiShow = function (cmd) {
                    return function () {
                      let closedNode = editor.selection.getRange().getClosedNode();
                      if (!closedNode || closedNode.tagName !== "IMG") {
                        return false
                      }
                      if ("formula" === cmd && closedNode.getAttribute("data-formula-image") !== null) {
                        return true
                      }
                      if ("insertimage" === cmd) {
                        return true
                      }
                      return false
                    }
                  }(cmd);
                  break
              }
              editorui.buttons[cmd] = ui;
              editor.addListener("selectionchange", function () {
                var unNeedCheckState = {edittable: 1};
                if (cmd in unNeedCheckState) return;
                var state = editor.queryCommandState(cmd);
                if (ui.getDom()) {
                  ui.setDisabled(state === -1);
                  ui.setChecked(state)
                }
              });
              return ui
            }
          })(ci.toLowerCase())
        }
      })(p, dialogBtns[p])
    }
    editorui.insertcode = function (editor, list, title) {
      list = editor.options["insertcode"] || [];
      title = editor.options.labelMap["insertcode"] || editor.getLang("labelMap.insertcode") || "";
      var items = [];
      utils.each(list, function (key, val) {
        items.push({
          label: key, value: val, theme: editor.options.theme, renderLabelHtml: function () {
            return '<div class="edui-label %%-label" >' + (this.label || "") + "</div>"
          }
        })
      });
      var ui = new editorui.Combox({
        editor: editor, items: items, onselect: function (t, index) {
          editor.execCommand("insertcode", this.items[index].value)
        }, onbuttonclick: function () {
          this.showPopup()
        }, title: title, initValue: title, className: "edui-for-insertcode", indexByValue: function (value) {
          if (value) {
            for (var i = 0, ci; ci = this.items[i]; i++) {
              if (ci.value.indexOf(value) != -1) return i
            }
          }
          return -1
        }
      });
      editorui.buttons["insertcode"] = ui;
      editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState("insertcode");
          if (state == -1) {
            ui.setDisabled(true)
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue("insertcode");
            if (!value) {
              ui.setValue(title);
              return
            }
            value && (value = value.replace(/['"]/g, "").split(",")[0]);
            ui.setValue(value)
          }
        }
      });
      return ui
    };
    editorui.fontfamily = function (editor, list, title) {
      list = editor.options["fontfamily"] || [];
      title = editor.options.labelMap["fontfamily"] || editor.getLang("labelMap.fontfamily") || "";
      if (!list.length) return;
      for (var i = 0, ci, items = []; ci = list[i]; i++) {
        var langLabel = editor.getLang("fontfamily")[ci.name] || "";
        (function (key, val) {
          items.push({
            label: key, value: val, theme: editor.options.theme, renderLabelHtml: function () {
              return '<div class="edui-label %%-label" style="font-family:' + utils.unhtml(this.value) + '">' + (this.label || "") + "</div>"
            }
          })
        })(ci.label || langLabel, ci.val)
      }
      var ui = new editorui.Combox({
        editor: editor, items: items, onselect: function (t, index) {
          editor.execCommand("FontFamily", this.items[index].value)
        }, onbuttonclick: function () {
          this.showPopup()
        }, title: title, initValue: title, className: "edui-for-fontfamily", indexByValue: function (value) {
          if (value) {
            for (var i = 0, ci; ci = this.items[i]; i++) {
              if (ci.value.indexOf(value) != -1) return i
            }
          }
          return -1
        }
      });
      editorui.buttons["fontfamily"] = ui;
      editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState("FontFamily");
          if (state == -1) {
            ui.setDisabled(true)
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue("FontFamily");
            value && (value = value.replace(/['"]/g, "").split(",")[0]);
            ui.setValue(value)
          }
        }
      });
      return ui
    };
    editorui.fontsize = function (editor, list, title) {
      title = editor.options.labelMap["fontsize"] || editor.getLang("labelMap.fontsize") || "";
      list = list || editor.options["fontsize"] || [];
      if (!list.length) return;
      var items = [];
      for (var i = 0; i < list.length; i++) {
        var size = list[i] + "px";
        items.push({
          label: size, value: size, theme: editor.options.theme, renderLabelHtml: function () {
            return '<div class="edui-label %%-label" style="line-height:1;font-size:' + this.value + '">' + (this.label || "") + "</div>"
          }
        })
      }
      var ui = new editorui.Combox({
        editor: editor, items: items, title: title, initValue: title, onselect: function (t, index) {
          editor.execCommand("FontSize", this.items[index].value)
        }, onbuttonclick: function () {
          this.showPopup()
        }, className: "edui-for-fontsize"
      });
      editorui.buttons["fontsize"] = ui;
      editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState("FontSize");
          if (state == -1) {
            ui.setDisabled(true)
          } else {
            ui.setDisabled(false);
            ui.setValue(editor.queryCommandValue("FontSize"))
          }
        }
      });
      return ui
    };
    editorui.paragraph = function (editor, list, title) {
      title = editor.options.labelMap["paragraph"] || editor.getLang("labelMap.paragraph") || "";
      list = editor.options["paragraph"] || [];
      if (utils.isEmptyObject(list)) return;
      var items = [];
      for (var i in list) {
        items.push({
          value: i, label: list[i] || editor.getLang("paragraph")[i], theme: editor.options.theme, renderLabelHtml: function () {
            return '<div class="edui-label %%-label"><span class="edui-for-' + this.value + '">' + (this.label || "") + "</span></div>"
          }
        })
      }
      var ui = new editorui.Combox({
        editor: editor, items: items, title: title, initValue: title, className: "edui-for-paragraph", onselect: function (t, index) {
          editor.execCommand("Paragraph", this.items[index].value)
        }, onbuttonclick: function () {
          this.showPopup()
        }
      });
      editorui.buttons["paragraph"] = ui;
      editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState("Paragraph");
          if (state == -1) {
            ui.setDisabled(true)
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue("Paragraph");
            var index = ui.indexByValue(value);
            if (index != -1) {
              ui.setValue(value)
            } else {
              ui.setValue(ui.initValue)
            }
          }
        }
      });
      return ui
    };
    editorui.customstyle = function (editor) {
      var list = editor.options["customstyle"] || [], title = editor.options.labelMap["customstyle"] || editor.getLang("labelMap.customstyle") || "";
      if (!list.length) return;
      var langCs = editor.getLang("customstyle");
      for (var i = 0, items = [], t; t = list[i++];) {
        (function (t) {
          var ck = {};
          ck.label = t.label ? t.label : langCs[t.name];
          ck.style = t.style;
          ck.className = t.className;
          ck.tag = t.tag;
          items.push({
            label: ck.label, value: ck, theme: editor.options.theme, renderLabelHtml: function () {
              return '<div class="edui-label %%-label">' + "<" + ck.tag + " " + (ck.className ? ' class="' + ck.className + '"' : "") + (ck.style ? ' style="' + ck.style + '"' : "") + ">" + ck.label + "</" + ck.tag + ">" + "</div>"
            }
          })
        })(t)
      }
      var ui = new editorui.Combox({
        editor: editor, items: items, title: title, initValue: title, className: "edui-for-customstyle", onselect: function (t, index) {
          editor.execCommand("customstyle", this.items[index].value)
        }, onbuttonclick: function () {
          this.showPopup()
        }, indexByValue: function (value) {
          for (var i = 0, ti; ti = this.items[i++];) {
            if (ti.label == value) {
              return i - 1
            }
          }
          return -1
        }
      });
      editorui.buttons["customstyle"] = ui;
      editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState("customstyle");
          if (state == -1) {
            ui.setDisabled(true)
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue("customstyle");
            var index = ui.indexByValue(value);
            if (index != -1) {
              ui.setValue(value)
            } else {
              ui.setValue(ui.initValue)
            }
          }
        }
      });
      return ui
    };
    editorui.inserttable = function (editor, iframeUrl, title) {
      title = editor.options.labelMap["inserttable"] || editor.getLang("labelMap.inserttable") || "";
      var ui = new editorui.TableButton({
        editor: editor, title: title, className: "edui-for-inserttable", onpicktable: function (t, numCols, numRows) {
          editor.execCommand("InsertTable", {numRows: numRows, numCols: numCols, border: 1})
        }, onbuttonclick: function () {
          this.showPopup()
        }
      });
      editorui.buttons["inserttable"] = ui;
      editor.addListener("selectionchange", function () {
        ui.setDisabled(editor.queryCommandState("inserttable") == -1)
      });
      return ui
    };
    editorui.lineheight = function (editor) {
      var val = editor.options.lineheight || [];
      if (!val.length) return;
      for (var i = 0, ci, items = []; ci = val[i++];) {
        items.push({
          label: ci, value: ci, theme: editor.options.theme, onclick: function () {
            editor.execCommand("lineheight", this.value)
          }
        })
      }
      var ui = new editorui.MenuButton({
        editor: editor, className: "edui-for-lineheight", title: editor.options.labelMap["lineheight"] || editor.getLang("labelMap.lineheight") || "", items: items, onbuttonclick: function () {
          var value = editor.queryCommandValue("LineHeight") || this.value;
          editor.execCommand("LineHeight", value)
        }
      });
      editorui.buttons["lineheight"] = ui;
      editor.addListener("selectionchange", function () {
        var state = editor.queryCommandState("LineHeight");
        if (state == -1) {
          ui.setDisabled(true)
        } else {
          ui.setDisabled(false);
          var value = editor.queryCommandValue("LineHeight");
          value && ui.setValue((value + "").replace(/cm/, ""));
          ui.setChecked(state)
        }
      });
      return ui
    };
    var rowspacings = ["top", "bottom"];
    for (var r = 0, ri; ri = rowspacings[r++];) {
      (function (cmd) {
        editorui["rowspacing" + cmd] = function (editor) {
          var val = editor.options["rowspacing" + cmd] || [];
          if (!val.length) return null;
          for (var i = 0, ci, items = []; ci = val[i++];) {
            items.push({
              label: ci, value: ci, theme: editor.options.theme, onclick: function () {
                editor.execCommand("rowspacing", this.value, cmd)
              }
            })
          }
          var ui = new editorui.MenuButton({
            editor: editor, className: "edui-for-rowspacing" + cmd, title: editor.options.labelMap["rowspacing" + cmd] || editor.getLang("labelMap.rowspacing" + cmd) || "", items: items, onbuttonclick: function () {
              var value = editor.queryCommandValue("rowspacing", cmd) || this.value;
              editor.execCommand("rowspacing", value, cmd)
            }
          });
          editorui.buttons[cmd] = ui;
          editor.addListener("selectionchange", function () {
            var state = editor.queryCommandState("rowspacing", cmd);
            if (state == -1) {
              ui.setDisabled(true)
            } else {
              ui.setDisabled(false);
              var value = editor.queryCommandValue("rowspacing", cmd);
              value && ui.setValue((value + "").replace(/%/, ""));
              ui.setChecked(state)
            }
          });
          return ui
        }
      })(ri)
    }
    var lists = ["insertorderedlist", "insertunorderedlist"];
    for (var l = 0, cl; cl = lists[l++];) {
      (function (cmd) {
        editorui[cmd] = function (editor) {
          var vals = editor.options[cmd], _onMenuClick = function () {
            editor.execCommand(cmd, this.value)
          }, items = [];
          for (var i in vals) {
            items.push({label: vals[i] || editor.getLang()[cmd][i] || "", value: i, theme: editor.options.theme, onclick: _onMenuClick})
          }
          var ui = new editorui.MenuButton({
            editor: editor, className: "edui-for-" + cmd, title: editor.getLang("labelMap." + cmd) || "", items: items, onbuttonclick: function () {
              var value = editor.queryCommandValue(cmd) || this.value;
              editor.execCommand(cmd, value)
            }
          });
          editorui.buttons[cmd] = ui;
          editor.addListener("selectionchange", function () {
            var state = editor.queryCommandState(cmd);
            if (state == -1) {
              ui.setDisabled(true)
            } else {
              ui.setDisabled(false);
              var value = editor.queryCommandValue(cmd);
              ui.setValue(value);
              ui.setChecked(state)
            }
          });
          return ui
        }
      })(cl)
    }
    editorui.fullscreen = function (editor, title) {
      title = editor.options.labelMap["fullscreen"] || editor.getLang("labelMap.fullscreen") || "";
      var ui = new editorui.Button({
        className: "edui-for-fullscreen", title: title, theme: editor.options.theme, onclick: function () {
          if (editor.ui) {
            editor.ui.setFullScreen(!editor.ui.isFullScreen())
          }
          this.setChecked(editor.ui.isFullScreen())
        }
      });
      editorui.buttons["fullscreen"] = ui;
      editor.addListener("selectionchange", function () {
        var state = editor.queryCommandState("fullscreen");
        ui.setDisabled(state == -1);
        ui.setChecked(editor.ui.isFullScreen())
      });
      return ui
    };
    editorui["emotion"] = function (editor, iframeUrl) {
      var cmd = "emotion";
      var ui = new editorui.MultiMenuPop({
        title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd + "") || "",
        editor: editor,
        className: "edui-for-" + cmd,
        iframeUrl: editor.ui.mapUrl(iframeUrl || (editor.options.dialogIframeUrlMap || {})[cmd] || dialogIframeUrlMap[cmd])
      });
      editorui.buttons[cmd] = ui;
      editor.addListener("selectionchange", function () {
        ui.setDisabled(editor.queryCommandState(cmd) == -1)
      });
      return ui
    };
    editorui["autotypeset"] = function (editor) {
      var ui = new editorui.AutoTypeSetButton({
        editor: editor, title: editor.options.labelMap["autotypeset"] || editor.getLang("labelMap.autotypeset") || "", className: "edui-for-autotypeset", onbuttonclick: function () {
          editor.execCommand("autotypeset")
        }
      });
      editorui.buttons["autotypeset"] = ui;
      editor.addListener("selectionchange", function () {
        ui.setDisabled(editor.queryCommandState("autotypeset") == -1)
      });
      return ui
    };
    editorui["simpleupload"] = function (editor) {
      var name = "simpleupload", ui = new editorui.Button({
        className: "edui-for-" + name, title: editor.options.labelMap[name] || editor.getLang("labelMap." + name) || "", onclick: function () {
        }, theme: editor.options.theme, showText: false
      });
      editorui.buttons[name] = ui;
      editor.addListener("ready", function () {
        var b = ui.getDom("body"), iconSpan = b.children[0];
        editor.fireEvent("simpleuploadbtnready", iconSpan)
      });
      editor.addListener("selectionchange", function (type, causeByUi, uiReady) {
        var state = editor.queryCommandState(name);
        if (state == -1) {
          ui.setDisabled(true);
          ui.setChecked(false)
        } else {
          if (!uiReady) {
            ui.setDisabled(false);
            ui.setChecked(state)
          }
        }
      });
      return ui
    }
  })();
  (function () {
    var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, domUtils = baidu.editor.dom.domUtils;
    var nodeStack = [];

    function EditorUI(options) {
      this.initOptions(options);
      this.initEditorUI()
    }

    EditorUI.prototype = {
      uiName: "editor", initEditorUI: function () {
        this.editor.ui = this;
        this._dialogs = {};
        this.initUIBase();
        this._initToolbars();
        var editor = this.editor, me = this;
        editor.addListener("ready", function () {
          editor.getDialog = function (name) {
            return editor.ui._dialogs[name + "Dialog"]
          };
          domUtils.on(editor.window, "scroll", function (evt) {
            baidu.editor.ui.Popup.postHide(evt)
          });
          editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
          UE.browser.ie && UE.browser.version === 6 && editor.container.ownerDocument.execCommand("BackgroundImageCache", false, true);
          if (editor.options.elementPathEnabled) {
            editor.ui.getDom("elementpath").innerHTML = '<div class="edui-editor-breadcrumb">' + editor.getLang("elementPathTip") + ":</div>"
          }
          if (editor.options.wordCount) {
            function countFn() {
              setCount(editor, me);
              domUtils.un(editor.document, "click", arguments.callee)
            }

            domUtils.on(editor.document, "click", countFn);
            editor.ui.getDom("wordcount").innerHTML = editor.getLang("wordCountTip")
          }
          editor.ui._scale();
          if (editor.options.scaleEnabled) {
            if (editor.autoHeightEnabled) {
              editor.disableAutoHeight()
            }
            me.enableScale()
          } else {
            me.disableScale()
          }
          if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) {
            editor.ui.getDom("elementpath").style.display = "none";
            editor.ui.getDom("wordcount").style.display = "none";
            editor.ui.getDom("scale").style.display = "none"
          }
          if (!editor.selection.isFocus()) return;
          editor.fireEvent("selectionchange", false, true)
        });
        editor.addListener("mousedown", function (t, evt) {
          var el = evt.target || evt.srcElement;
          baidu.editor.ui.Popup.postHide(evt, el);
          baidu.editor.ui.ShortCutMenu.postHide(evt)
        });
        editor.addListener("delcells", function () {
          if (UE.ui["edittip"]) {
            new UE.ui["edittip"](editor)
          }
          editor.getDialog("edittip").open()
        });
        var pastePop, isPaste = false, timer;
        editor.addListener("afterpaste", function () {
          if (editor.queryCommandState("pasteplain")) return;
          if (baidu.editor.ui.PastePicker) {
            pastePop = new baidu.editor.ui.Popup({content: new baidu.editor.ui.PastePicker({editor: editor}), editor: editor, className: "edui-wordpastepop"});
            pastePop.render()
          }
          isPaste = true
        });
        editor.addListener("afterinserthtml", function () {
          clearTimeout(timer);
          timer = setTimeout(function () {
            if (pastePop && (isPaste || editor.ui._isTransfer)) {
              if (pastePop.isHidden()) {
                var span = domUtils.createElement(editor.document, "span", {style: "line-height:0px;", innerHTML: "\ufeff"}), range = editor.selection.getRange();
                range.insertNode(span);
                var tmp = getDomNode(span, "firstChild", "previousSibling");
                tmp && pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
                domUtils.remove(span)
              } else {
                pastePop.show()
              }
              delete editor.ui._isTransfer;
              isPaste = false
            }
          }, 200)
        });
        editor.addListener("contextmenu", function (t, evt) {
          baidu.editor.ui.Popup.postHide(evt)
        });
        editor.addListener("keydown", function (t, evt) {
          if (pastePop) pastePop.dispose(evt);
          var keyCode = evt.keyCode || evt.which;
          if (evt.altKey && keyCode == 90) {
            UE.ui.buttons["fullscreen"].onclick()
          }
        });
        editor.addListener("wordcount", function (type) {
          setCount(this, me)
        });

        function setCount(editor, ui) {
          editor.setOpt({wordCount: true, maximumWords: 1e4, wordCountMsg: editor.options.wordCountMsg || editor.getLang("wordCountMsg"), wordOverFlowMsg: editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg")});
          var opt = editor.options, max = opt.maximumWords, msg = opt.wordCountMsg, errMsg = opt.wordOverFlowMsg, countDom = ui.getDom("wordcount");
          if (!opt.wordCount) {
            return
          }
          var count = editor.getContentLength(true);
          if (count > max) {
            countDom.innerHTML = errMsg;
            editor.fireEvent("wordcountoverflow")
          } else {
            countDom.innerHTML = msg.replace("{#leave}", max - count).replace("{#count}", count)
          }
        }

        editor.addListener("selectionchange", function () {
          if (editor.options.elementPathEnabled) {
            me[(editor.queryCommandState("elementpath") == -1 ? "dis" : "en") + "ableElementPath"]()
          }
          if (editor.options.scaleEnabled) {
            me[(editor.queryCommandState("scale") == -1 ? "dis" : "en") + "ableScale"]()
          }
        });
        var popup = new baidu.editor.ui.Popup({
          editor: editor, content: "", className: "edui-bubble", _onEditButtonClick: function () {
            this.hide();
            editor.ui._dialogs.linkDialog.open()
          }, _onImgEditButtonClick: function (name) {
            this.hide();
            editor.ui._dialogs[name] && editor.ui._dialogs[name].open()
          }, _onImgSetFloat: function (value) {
            this.hide();
            editor.execCommand("imagefloat", value)
          }, _setIframeAlign: function (value) {
            var frame = popup.anchorEl;
            var newFrame = frame.cloneNode(true);
            switch (value) {
              case-2:
                newFrame.setAttribute("align", "");
                break;
              case-1:
                newFrame.setAttribute("align", "left");
                break;
              case 1:
                newFrame.setAttribute("align", "right");
                break
            }
            frame.parentNode.insertBefore(newFrame, frame);
            domUtils.remove(frame);
            popup.anchorEl = newFrame;
            popup.showAnchor(popup.anchorEl)
          }, _updateIframe: function () {
            var frame = editor._iframe = popup.anchorEl;
            if (domUtils.hasClass(frame, "ueditor_baidumap")) {
              editor.selection.getRange().selectNode(frame).select();
              editor.ui._dialogs.mapDialog.open();
              popup.hide()
            } else {
              editor.ui._dialogs.insertframeDialog.open();
              popup.hide()
            }
          }, _onRemoveButtonClick: function (cmdName) {
            editor.execCommand(cmdName);
            this.hide()
          }, queryAutoHide: function (el) {
            if (el && el.ownerDocument == editor.document) {
              if (el.tagName.toLowerCase() == "img" || domUtils.findParentByTagName(el, "a", true)) {
                return el !== popup.anchorEl
              }
            }
            return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el)
          }
        });
        popup.render();
        if (editor.options.imagePopup) {
          editor.addListener("mouseover", function (t, evt) {
            evt = evt || window.event;
            var el = evt.target || evt.srcElement;
            if (editor.ui._dialogs.insertframeDialog && /iframe/gi.test(el.tagName)) {
              var html = popup.formatHtml("<nobr>" + '<span onclick=$$._setIframeAlign(-2) class="edui-clickable">' + editor.getLang("default") + '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(-1) class="edui-clickable">' + editor.getLang("justifyleft") + '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(1) class="edui-clickable">' + editor.getLang("justifyright") + "</span>&nbsp;&nbsp;" + ' <span onclick="$$._updateIframe( this);" class="edui-clickable">' + editor.getLang("modify") + "</span></nobr>");
              if (html) {
                popup.getDom("content").innerHTML = html;
                popup.anchorEl = el;
                popup.showAnchor(popup.anchorEl)
              } else {
                popup.hide()
              }
            }
          });
          editor.addListener("selectionchange", function (t, causeByUi) {
            if (!causeByUi) {
              return
            }
            var html = "", str = "", closedNode = editor.selection.getRange().getClosedNode(), dialogs = editor.ui._dialogs;
            if (closedNode && closedNode.tagName === "IMG") {
              var dialogName = "insertimageDialog";
              if (closedNode.className.indexOf("edui-faked-video") !== -1 || closedNode.className.indexOf("edui-upload-video") !== -1) {
                dialogName = "insertvideoDialog"
              }
              if (closedNode.className.indexOf("edui-faked-audio") !== -1 || closedNode.className.indexOf("edui-upload-audio") !== -1) {
                dialogName = "insertaudioDialog"
              }
              if (closedNode.getAttribute("anchorname")) {
                dialogName = "anchorDialog";
                html = popup.formatHtml("<nobr>" + '<span onclick=$$._onImgEditButtonClick("anchorDialog") class="edui-clickable">' + editor.getLang("modify") + "</span>&nbsp;&nbsp;" + "<span onclick=$$._onRemoveButtonClick('anchor') class=\"edui-clickable\">" + editor.getLang("delete") + "</span></nobr>")
              }
              if (domUtils.hasClass(closedNode, "uep-loading") || domUtils.hasClass(closedNode, "uep-loading-error")) {
                dialogName = ""
              }
              if (!dialogs[dialogName]) {
                return
              }
              var actions = [];
              if (closedNode.getAttribute("data-word-image")) {
                actions.push("<span onclick=\"$$._onImgEditButtonClick('wordimageDialog');\" class='edui-clickable edui-popup-action-item'>" + editor.getLang("save") + "</span>")
              } else {
              }
              if (actions.length > 0) {
                actions.unshift("<nobr>");
                actions.push("</nobr>")
              }
              !html && (html = popup.formatHtml(actions.join("")))
            }
            if (editor.ui._dialogs.linkDialog) {
              var link = editor.queryCommandValue("link");
              var url;
              if (link && (url = link.getAttribute("_href") || link.getAttribute("href", 2))) {
                var txt = url;
                if (url.length > 30) {
                  txt = url.substring(0, 20) + "..."
                }
                if (html) {
                  html += '<div style="height:5px;"></div>'
                }
                html += popup.formatHtml("<nobr>" + editor.getLang("anchorMsg") + ': <a target="_blank" href="' + url + '" title="' + url + '" >' + txt + "</a>" + ' <span class="edui-clickable" onclick="$$._onEditButtonClick();">' + editor.getLang("modify") + "</span>" + ' <span class="edui-clickable" onclick="$$._onRemoveButtonClick(\'unlink\');"> ' + editor.getLang("clear") + "</span></nobr>");
                popup.showAnchor(link)
              }
            }
            if (html) {
              popup.getDom("content").innerHTML = html;
              popup.anchorEl = closedNode || link;
              popup.showAnchor(popup.anchorEl)
            } else {
              popup.hide()
            }
          })
        }
      }, _initToolbars: function () {
        var editor = this.editor;
        var toolbars = this.toolbars || [];
        if (toolbars[0]) {
          toolbars[0].unshift("message")
        }
        var toolbarUis = [];
        var extraUIs = [];
        for (var i = 0; i < toolbars.length; i++) {
          var toolbar = toolbars[i];
          var toolbarUi = new baidu.editor.ui.Toolbar({theme: editor.options.theme});
          for (var j = 0; j < toolbar.length; j++) {
            var toolbarItem = toolbar[j];
            var toolbarItemUi = null;
            if (typeof toolbarItem == "string") {
              toolbarItem = toolbarItem.toLowerCase();
              if (toolbarItem === "|") {
                toolbarItem = "Separator"
              }
              if (toolbarItem === "||") {
                toolbarItem = "Breakline"
              }
              var ui = baidu.editor.ui[toolbarItem];
              if (ui) {
                if (utils.isFunction(ui)) {
                  toolbarItemUi = new baidu.editor.ui[toolbarItem](editor)
                } else {
                  if (ui.id && ui.id !== editor.key) {
                    continue
                  }
                  var itemUI = ui.execFn.call(editor, editor, toolbarItem);
                  if (itemUI) {
                    if (ui.index === undefined) {
                      toolbarUi.add(itemUI);
                      continue
                    } else {
                      extraUIs.push({index: ui.index, itemUI: itemUI})
                    }
                  }
                }
              }
              if (toolbarItem === "fullscreen") {
                if (toolbarUis && toolbarUis[0]) {
                  toolbarUis[0].items.splice(0, 0, toolbarItemUi)
                } else {
                  toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi)
                }
                continue
              }
            } else {
              toolbarItemUi = toolbarItem
            }
            if (toolbarItemUi && toolbarItemUi.id) {
              toolbarUi.add(toolbarItemUi)
            }
          }
          toolbarUis[i] = toolbarUi
        }
        utils.each(extraUIs, function (obj) {
          toolbarUi.add(obj.itemUI, obj.index)
        });
        this.toolbars = toolbarUis
      }, getHtmlTpl: function () {
        return '<div id="##" class="%%">' + '<div id="##_toolbarbox" class="%%-toolbarbox">' + (this.toolbars.length ? '<div id="##_toolbarboxouter" class="%%-toolbarboxouter"><div class="%%-toolbarboxinner">' + this.renderToolbarBoxHtml() + "</div></div>" : "") + '<div id="##_toolbarmsg" class="%%-toolbarmsg" style="display:none;">' + '<div id = "##_upload_dialog" class="%%-toolbarmsg-upload" onclick="$$.showWordImageDialog();">' + this.editor.getLang("clickToUpload") + "</div>" + '<div class="%%-toolbarmsg-close" onclick="$$.hideToolbarMsg();">x</div>' + '<div id="##_toolbarmsg_label" class="%%-toolbarmsg-label"></div>' + '<div style="height:0;overflow:hidden;clear:both;"></div>' + "</div>" + '<div id="##_message_holder" class="%%-messageholder"></div>' + "</div>" + '<div id="##_iframeholder" class="%%-iframeholder">' + "</div>" + '<div id="##_bottombar" class="%%-bottomContainer"><table><tr>' + '<td id="##_elementpath" class="%%-bottombar"></td>' + '<td id="##_wordcount" class="%%-wordcount"></td>' + '<td id="##_scale" class="%%-scale"><div class="%%-icon"></div></td>' + "</tr></table></div>" + '<div id="##_scalelayer"></div>' + "</div>"
      }, showWordImageDialog: function () {
        this._dialogs["wordimageDialog"].open()
      }, renderToolbarBoxHtml: function () {
        var buff = [];
        for (var i = 0; i < this.toolbars.length; i++) {
          buff.push(this.toolbars[i].renderHtml())
        }
        return buff.join("")
      }, setFullScreen: function (fullscreen) {
        var editor = this.editor, container = editor.container.parentNode.parentNode;
        if (this._fullscreen != fullscreen) {
          this._fullscreen = fullscreen;
          this.editor.fireEvent("beforefullscreenchange", fullscreen);
          if (baidu.editor.browser.gecko) {
            var bk = editor.selection.getRange().createBookmark()
          }
          if (fullscreen) {
            this._bakEditorContaninerWidth = editor.iframe.parentNode.style.width;
            while (container.tagName !== "BODY") {
              var position = baidu.editor.dom.domUtils.getComputedStyle(container, "position");
              nodeStack.push(position);
              container.style.position = "static";
              container = container.parentNode
            }
            this._bakHtmlOverflow = document.documentElement.style.overflow;
            this._bakBodyOverflow = document.body.style.overflow;
            this._bakAutoHeight = this.editor.autoHeightEnabled;
            this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
            if (this._bakAutoHeight) {
              editor.autoHeightEnabled = false;
              this.editor.disableAutoHeight()
            }
            document.documentElement.style.overflow = "hidden";
            window.scrollTo(0, window.scrollY);
            this._bakCssText = this.getDom().style.cssText;
            this._bakCssText1 = this.getDom("iframeholder").style.cssText;
            editor.iframe.parentNode.style.width = "";
            this._updateFullScreen()
          } else {
            while (container.tagName !== "BODY") {
              container.style.position = nodeStack.shift();
              container = container.parentNode
            }
            this.getDom().style.cssText = this._bakCssText;
            this.getDom("iframeholder").style.cssText = this._bakCssText1;
            if (this._bakAutoHeight) {
              editor.autoHeightEnabled = true;
              this.editor.enableAutoHeight()
            }
            document.documentElement.style.overflow = this._bakHtmlOverflow;
            document.body.style.overflow = this._bakBodyOverflow;
            editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth;
            window.scrollTo(0, this._bakScrollTop)
          }
          if (browser.gecko && editor.body.contentEditable === "true") {
            var input = document.createElement("input");
            document.body.appendChild(input);
            editor.body.contentEditable = false;
            setTimeout(function () {
              input.focus();
              setTimeout(function () {
                editor.body.contentEditable = true;
                editor.fireEvent("fullscreenchanged", fullscreen);
                editor.selection.getRange().moveToBookmark(bk).select(true);
                baidu.editor.dom.domUtils.remove(input);
                fullscreen && window.scroll(0, 0)
              }, 0)
            }, 0)
          }
          if (editor.body.contentEditable === "true") {
            this.editor.fireEvent("fullscreenchanged", fullscreen);
            this.triggerLayout()
          }
        }
      }, _updateFullScreen: function () {
        if (this._fullscreen) {
          var vpRect = uiUtils.getViewportRect();
          this.getDom().style.cssText = "border:0;position:absolute;left:0;top:var(--ueditor-top-offset," + (this.editor.options.topOffset || 0) + "px);width:" + vpRect.width + "px;height:" + vpRect.height + "px;z-index:" + (this.getDom().style.zIndex * 1 + 100);
          uiUtils.setViewportOffset(this.getDom(), {left: 0});
          this.editor.setHeight(vpRect.height - this.getDom("toolbarbox").offsetHeight - this.getDom("bottombar").offsetHeight - (this.editor.options.topOffset || 0), true);
          if (browser.gecko) {
            try {
              window.onresize()
            } catch (e) {
            }
          }
        }
      }, _updateElementPath: function () {
        var bottom = this.getDom("elementpath"), list;
        if (this.elementPathEnabled && (list = this.editor.queryCommandValue("elementpath"))) {
          var buff = [];
          for (var i = 0, ci; ci = list[i]; i++) {
            buff[i] = this.formatHtml('<span unselectable="on" onclick="$$.editor.execCommand(&quot;elementpath&quot;, &quot;' + i + '&quot;);">' + ci + "</span>")
          }
          bottom.innerHTML = '<div class="edui-editor-breadcrumb" onmousedown="return false;">' + this.editor.getLang("elementPathTip") + ": " + buff.join(" &gt; ") + "</div>"
        } else {
          bottom.style.display = "none"
        }
      }, disableElementPath: function () {
        var bottom = this.getDom("elementpath");
        bottom.innerHTML = "";
        bottom.style.display = "none";
        this.elementPathEnabled = false
      }, enableElementPath: function () {
        var bottom = this.getDom("elementpath");
        bottom.style.display = "";
        this.elementPathEnabled = true;
        this._updateElementPath()
      }, _scale: function () {
        var doc = document, editor = this.editor, editorHolder = editor.container, editorDocument = editor.document, toolbarBox = this.getDom("toolbarbox"), bottombar = this.getDom("bottombar"), scale = this.getDom("scale"),
          scalelayer = this.getDom("scalelayer");
        var isMouseMove = false, position = null, minEditorHeight = 0, minEditorWidth = editor.options.minFrameWidth, pageX = 0, pageY = 0, scaleWidth = 0, scaleHeight = 0;

        function down() {
          position = domUtils.getXY(editorHolder);
          if (!minEditorHeight) {
            minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight
          }
          scalelayer.style.cssText = "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + editorHolder.offsetWidth + "px;height:" + editorHolder.offsetHeight + "px;z-index:" + (editor.options.zIndex + 1);
          domUtils.on(doc, "mousemove", move);
          domUtils.on(editorDocument, "mouseup", up);
          domUtils.on(doc, "mouseup", up)
        }

        var me = this;
        this.editor.addListener("fullscreenchanged", function (e, fullScreen) {
          if (fullScreen) {
            me.disableScale()
          } else {
            if (me.editor.options.scaleEnabled) {
              me.enableScale();
              var tmpNode = me.editor.document.createElement("span");
              me.editor.body.appendChild(tmpNode);
              me.editor.body.style.height = Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + "px";
              domUtils.remove(tmpNode)
            }
          }
        });

        function move(event) {
          clearSelection();
          var e = event || window.event;
          pageX = e.pageX || doc.documentElement.scrollLeft + e.clientX;
          pageY = e.pageY || doc.documentElement.scrollTop + e.clientY;
          scaleWidth = pageX - position.x;
          scaleHeight = pageY - position.y;
          if (scaleWidth >= minEditorWidth) {
            isMouseMove = true;
            scalelayer.style.width = scaleWidth + "px"
          }
          if (scaleHeight >= minEditorHeight) {
            isMouseMove = true;
            scalelayer.style.height = scaleHeight + "px"
          }
        }

        function up() {
          if (isMouseMove) {
            isMouseMove = false;
            editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
            editorHolder.style.width = editor.ui._actualFrameWidth + "px";
            editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2, true)
          }
          if (scalelayer) {
            scalelayer.style.display = "none"
          }
          clearSelection();
          domUtils.un(doc, "mousemove", move);
          domUtils.un(editorDocument, "mouseup", up);
          domUtils.un(doc, "mouseup", up)
        }

        function clearSelection() {
          if (browser.ie) doc.selection.clear(); else window.getSelection().removeAllRanges()
        }

        this.enableScale = function () {
          if (editor.queryCommandState("source") == 1) return;
          scale.style.display = "";
          this.scaleEnabled = true;
          domUtils.on(scale, "mousedown", down)
        };
        this.disableScale = function () {
          scale.style.display = "none";
          this.scaleEnabled = false;
          domUtils.un(scale, "mousedown", down)
        }
      }, isFullScreen: function () {
        return this._fullscreen
      }, postRender: function () {
        UIBase.prototype.postRender.call(this);
        for (var i = 0; i < this.toolbars.length; i++) {
          this.toolbars[i].postRender()
        }
        var me = this;
        var timerId, domUtils = baidu.editor.dom.domUtils, updateFullScreenTime = function () {
          clearTimeout(timerId);
          timerId = setTimeout(function () {
            me._updateFullScreen()
          })
        };
        domUtils.on(window, "resize", updateFullScreenTime);
        me.addListener("destroy", function () {
          domUtils.un(window, "resize", updateFullScreenTime);
          clearTimeout(timerId)
        })
      }, showToolbarMsg: function (msg, flag) {
        this.getDom("toolbarmsg_label").innerHTML = msg;
        this.getDom("toolbarmsg").style.display = "";
        if (!flag) {
          var w = this.getDom("upload_dialog");
          w.style.display = "none"
        }
      }, hideToolbarMsg: function () {
        this.getDom("toolbarmsg").style.display = "none"
      }, mapUrl: function (url) {
        return url ? url.replace("~/", this.editor.options.UEDITOR_CORS_URL || "") : ""
      }, triggerLayout: function () {
        var dom = this.getDom();
        if (dom.style.zoom == "1") {
          dom.style.zoom = "100%"
        } else {
          dom.style.zoom = "1"
        }
      }
    };
    utils.inherits(EditorUI, baidu.editor.ui.UIBase);
    var instances = {};
    UE.ui.Editor = function (options) {
      var editor = new UE.Editor(options);
      editor.options.editor = editor;
      utils.loadFile(document, {href: editor.options.themePath + editor.options.theme + "/css/ueditor.css?98125a73", tag: "link", type: "text/css", rel: "stylesheet"});
      var oldRender = editor.render;
      editor.render = function (holder) {
        if (holder.constructor === String) {
          editor.key = holder;
          instances[holder] = editor
        }
        utils.domReady(function () {
          editor.langIsReady ? renderUI() : editor.addListener("langReady", renderUI);

          function renderUI() {
            editor.setOpt({labelMap: editor.options.labelMap || editor.getLang("labelMap")});
            new EditorUI(editor.options);
            if (holder) {
              if (holder.constructor === String) {
                holder = document.getElementById(holder)
              }
              holder && holder.getAttribute("name") && (editor.options.textarea = holder.getAttribute("name"));
              if (holder && /script|textarea/gi.test(holder.tagName)) {
                var newDiv = document.createElement("div");
                holder.parentNode.insertBefore(newDiv, holder);
                var cont = holder.value || holder.innerHTML;
                editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) ? editor.options.initialContent : cont.replace(/>[\n\r\t]+([ ]{4})+/g, ">").replace(/[\n\r\t]+([ ]{4})+</g, "<").replace(/>[\n\r\t]+</g, "><");
                holder.className && (newDiv.className = holder.className);
                holder.style.cssText && (newDiv.style.cssText = holder.style.cssText);
                if (/textarea/i.test(holder.tagName)) {
                  editor.textarea = holder;
                  editor.textarea.style.display = "none"
                } else {
                  holder.parentNode.removeChild(holder)
                }
                if (holder.id) {
                  newDiv.id = holder.id;
                  domUtils.removeAttributes(holder, "id")
                }
                holder = newDiv;
                holder.innerHTML = ""
              }
            }
            domUtils.addClass(holder, "edui-" + editor.options.theme);
            editor.ui.render(holder);
            var opt = editor.options;
            editor.container = editor.ui.getDom();
            var parents = domUtils.findParents(holder, true);
            var displays = [];
            for (var i = 0, ci; ci = parents[i]; i++) {
              displays[i] = ci.style.display;
              ci.style.display = "block"
            }
            if (opt.initialFrameWidth) {
              opt.minFrameWidth = opt.initialFrameWidth
            } else {
              opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
              var styleWidth = holder.style.width;
              if (/%$/.test(styleWidth)) {
                opt.initialFrameWidth = styleWidth
              }
            }
            if (opt.initialFrameHeight) {
              opt.minFrameHeight = opt.initialFrameHeight
            } else {
              opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight
            }
            for (var i = 0, ci; ci = parents[i]; i++) {
              ci.style.display = displays[i]
            }
            if (holder.style.height) {
              holder.style.height = ""
            }
            editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? "" : "px");
            editor.container.style.zIndex = opt.zIndex;
            oldRender.call(editor, editor.ui.getDom("iframeholder"));
            editor.fireEvent("afteruiready")
          }
        })
      };
      return editor
    };
    UE.getEditor = function (id, opt) {
      var editor = instances[id];
      if (!editor) {
        editor = instances[id] = new UE.ui.Editor(opt);
        editor.render(id)
      }
      return editor
    };
    UE.delEditor = function (id) {
      var editor;
      if (editor = instances[id]) {
        editor.key && editor.destroy();
        delete instances[id]
      }
    };
    UE.registerUI = function (uiName, fn, index, editorId) {
      utils.each(uiName.split(/\s+/), function (name) {
        baidu.editor.ui[name] = {id: editorId, execFn: fn, index: index}
      })
    }
  })();
  UE.registerUI("message", function (editor) {
    var editorui = baidu.editor.ui;
    var Message = editorui.Message;
    var holder;
    var _messageItems = [];
    var me = editor;
    me.setOpt("enableMessageShow", true);
    if (me.getOpt("enableMessageShow") === false) {
      return
    }
    me.addListener("ready", function () {
      holder = document.getElementById(me.ui.id + "_message_holder");
      updateHolderPos();
      setTimeout(function () {
        updateHolderPos()
      }, 500)
    });
    me.addListener("showmessage", function (type, opt) {
      opt = utils.isString(opt) ? {content: opt} : opt;
      var message = new Message({timeout: opt.timeout, type: opt.type, content: opt.content, keepshow: opt.keepshow, editor: me}), mid = opt.id || "msg_" + (+new Date).toString(36);
      message.render(holder);
      _messageItems[mid] = message;
      message.reset(opt);
      updateHolderPos();
      return mid
    });
    me.addListener("updatemessage", function (type, id, opt) {
      opt = utils.isString(opt) ? {content: opt} : opt;
      var message = _messageItems[id];
      message.render(holder);
      message && message.reset(opt)
    });
    me.addListener("hidemessage", function (type, id) {
      var message = _messageItems[id];
      message && message.hide()
    });

    function updateHolderPos() {
      if (!holder || !me.ui) return;
      var toolbarbox = me.ui.getDom("toolbarbox");
      if (toolbarbox) {
        holder.style.top = toolbarbox.offsetHeight + 3 + "px"
      }
      holder.style.zIndex = Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1
    }
  })
})();
